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地址格式如下所示:
https://localhost/userapi.php?id=1×tamp=1519552181
修正上例中的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 如下所示:
http://localhost/userapi.php?id=1×tamp=1527068730
(1)得到参数数组:['timestamp'=> 1527068730, 'id'=>100]。
(2)键名根据 ASCII 码进行排序后:['id'=>100, 'timestamp'=> 1527068730]。
(3)组合成字符串:id=100timestamp=1527068730。
(4)利用sha1()函数加密得到fd8cc3348652b9cbf2714689ab7ee9105da67cf4。
客户端和API做事器端署名的打算方法相同,打算后的要求URL地址如下所示:
http://localhost/userapi.php?id=1×tamp=1527068730&sign=fd8cc3348652b9cbf2714689ab7ee9105da67cf4
连续修正上例中的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”字符串,这个可能性就太低了。