您的位置 首页 php

《细说PHP》第四版 样章 第23章 自定义PHP接口规范 5

23.3 接口的安全控制规范

23.2节的示例实现了一个简单接口,但是这个接口此时是在“裸奔”的。因为这个接口所有人都可以请求,不仅我们的客户端可以正常访问数据,如果有人使用如fiddler、wireshark等 抓包工具 ,就很容易获取这个API地址,可以随意地请求获取或篡改我们的数据,这很显然是不安全的。因此,在设计接口时必须加上安全控制这一环节。

23.3.1 API安全控制原则

由于Web API是基于互联网的应用,因此对安全性的要求远比在本地访问数据库严格得多。一般通用的做法是,采用参数加密签名方式传递,即在传递参数时,增加一个加密签名,在服务器端验证签名内容,防止被篡改。对一般的接口访问,只需要使用用户身份的token进行校验,只有检查通过才允许访问数据。API常用的安全控制原则有以下几种:

(1)使用用户名密码。这种方式比较简单,可以有效识别用户的身份(如用户信息、密码,或者相关的接口权限等)。验证成功后,返回相关的数据。

(2)使用安全签名。这种方式提交的数据,URL的连接参数是要经过一定规则的安全加密的,服务器收到数据后也经过同样的规则进行安全加密,确认数据没有被中途篡改后,再进行数据的修改处理。因此,我们可以为不同客户端,如Web、App等不同接入方式指定不同的密钥,但是密钥是双方约定的,并不在网络连接上传输,连接传输的一般是接入的“key”,服务器通过这个“key”来进行签名参数的加密对比。目前,微信后台的回调处理机制,采用的就是这种方法。

(3)公开的接口调用,不需要传入用户令牌,或者对参数进行加密签名,这种接口一般较少,只是提供一些很常规的数据显示而已。

23.3.2 API安全控制简单实现步骤

API的安全控制方法有很多,可以根据项目自身的情况定制一些方法,也可以借鉴一些大的平台处理接口的 算法 。本节通过一些简单的控制方式,来一步步实现API的安全访问控制。

1.增加时间戳参数

首先,我们在API的URL中添加一个时间戳参数,如“timestamp”,要求请求的客户端在请求接口的时候必须添加此参数。如果在请求的时候没有该参数,就不返回数据。另外,通过时间戳参数,也可以限制请求接口必须要在某个时间段内完成,即便有人发现了接口地址,也只能使用一段时间。加入时间戳参数后,请求接口的URL地址格式如下所示:

修改上例中的userclient.php文件,分别使用get()方法请求两次userapi.php接口,一次在URL加上“timestamp”参数,一次不加该参数。修改后代码片段如下所示:

同样地,修改userapi.php接口文件,判断在请求接口时,请求的URL中是否带有“timestamp”参数,并且限制该URL只能在5分钟内有效。修改后的代码片段如下所示:

运行的结果如图23-8所示。

图23-8 测试请求API的URL参数带有时间戳的结果

虽然我们实现了客户端软件在请求API时需要添加“timestamp”参数才能获取数据,但这样依然不能防止别人获取我们的数据,因为通过抓包工具依然是可以看到地址的,所以别人也可以添加 “timestamp”参数请求我们的接口。限时访问也只能瞒得过一般的程序员,稍微细心的程序员就会发现这个规律,他可以生成当前的时间戳,然后模拟参数发送请求来获取数据。

2. 增加签名参数

在发送API调用请求时,为了确保客户端应用与API服务器之间的安全通信,防止盗用URL、数据篡改等恶意攻击行为,在API验证规则中可以使用参数签名机制。过程是客户端应用在调用API之前,需要通过算法计算一个加密的签名,并追加到请求参数中,参数名可以为“sign”。API服务器在接收到请求时,使用同样的算法重新计算签名,并判断其值是否与应用传递来的“sign”参数值一致,以此判定当前API调用请求是否是被第三方伪造或篡改的。

签名的算法很多,本节模拟支付宝的签名算法。例如,制定一个规则,将所有URL的参数提取出来,然后根据参数名进行排序,再将排序后的数组拼接成 字符串 ,最后对该字符串进行 md5或 sha1 加密(建议使用sha1)后得到“sign”。例如,当前我们的URL 如下所示:

(1)得到参数数组:[‘timestamp’=> 1527068730, ‘id’=>100]。

(2)键名根据 ASCII 码进行排序后:[‘id’=>100, ‘timestamp’=> 1527068730]。

(3)组合成字符串:id=100timestamp=1527068730。

(4)使用sha1()函数加密得到fd8cc3348652b9cbf2714689ab7ee9105da67cf4。

客户端和API服务器端签名的计算方法相同,计算后的请求URL地址如下所示:

继续修改上例中的userclient.php文件,再分别使用get()方法请求3次userapi.php接口,第一次没有添加“sign”参数,第二次使用错误的“sign”参数,第三次使用全部正确的参数。并通过上面的算法生成“sign”参数。修改后代码片段如下所示:

同样地,修改userapi.php接口文件,判断在请求接口时,请求的URL是否带有“sign”参数,和客户端使用相同的算法计算签名,并和URL中接收到的客户端“sign”参数进行匹配,如果相同则返回数据,如果不同则可能被篡改,返回错误消息。修改后代码片段如下所示:

运行的结果如图23-9所示:

图23-9 测试请求API的URL参数带有sign的结果

通过签名参数,能大大提高接口的安全性,其他人不能随意地请求接口。虽然有人也可以抓取接口地址,但是也只能获取这一条数据,不能请求别的数据。例如,有人抓取了上例中的这个接口地址,它只能获取ID为1的文章。并且5分钟的时间内,它无法通过修改参数来获取ID为100的文章,因为一旦参数变化,“sign”参数校验就会失败。支付宝接口就是这样做的,避免交易金额随便被更改。

3. 引入token

虽然通过添加“时间戳”和“签名”参数,接口相对比较安全了,但是还是有隐患,如果别人知道了加密规则(当然规则可以变化,如倒序排序,或双层sha1加密等),采用相同的规则加密参数得到“sign”,就能接着获取其他的数据了。所以,需要再引入另一个元素“token”,它是一个约定值,相当于“暗号”,其实就是只有客户端和服务器端知道的一个随机字符串。当然这个“token”字符串在客户端用户那里是不可见的,如果客户端是App,代码是编译过的,客户端使用PHP程序,在服务器上不会传给用户。引入“token”只需要将这个随机的字符串加入sign 的计算中,就能再次提高接口的安全性。 继续修改上例中的userclient.php文件,引入“token”进入签名运算。修改后代码片段如下所示:

继续修改上例中的userapi.php文件,同样引入相同内容的“token”进入签名运算中。修改后代码片段如下所示:

再次运行后,和上例运行得到的结果相同。到此为止,我们的接口已经变得比较的安全了,其他人想要请求我们的接口,就必须知道我们的签名加密规则和随机的“token”字符串,这个可能性就太低了。

文章来源:智云一二三科技

文章标题:《细说PHP》第四版 样章 第23章 自定义PHP接口规范 5

文章地址:https://www.zhihuclub.com/149515.shtml

关于作者: 智云科技

热门文章

网站地图