API接口签名验证
2017-11-18 22:35
701 查看
在自己的实际工作中,会经常去调用网络上提供的一些开放性的API,其实自己在之前的公司也有写过API,但是可能是因为之前公司的项目规模比较小的原因,我们写的API一般是直接调用就可以可以了,对于API安全这块基本没有怎么重视。但是在有一次面试的过程中被问到API的安全问题,因为自己对这块知之甚少,无疑被虐得很惨,所以就回来研究了一下,虽然网上照的资料都已经写的非常详细了,但是自己决定还是自己再记一笔。
对于API安全这块,我们要考虑三个问题:
1.请求参数是否被篡改;
2.请求来源是否合法;
3.请求是否具有唯一性。
为了保证数据在通信时的安全性,我们可以采用参数签名的方式来进行相关验证。
案列分析
我们通过给某 [移动端(app)] 写 [后台接口(api)] 的案例进行分析:
客户端: 以下简称app
后台接口:以下简称api
我们通过app查询产品列表这个操作来进行分析:
app中点击查询按钮->调用api进行查询->返回查询结果->显示在app中
app调用:http://api.test.com/getproducts?参数1=value1…….
如上,这种方式简单粗暴,通过调用getproducts方法即可获取产品列表信息了,但是 这样的方式会存在很严重的安全性问题,没有进行任何的验证,大家都可以通过这个方法获取到产品列表,导致产品信息泄露。
那么,如何验证调用者身份呢?如何防止参数被篡改呢?
1.给app分配对应的key、secret(调用接口的人在在调用的时候就直接把key传过去,但是secret是不能够传递的,但是需要把key放在我们签名中加密,然后在后端,我们接到key之后,就去数据库中查询对应的secrect,然后再按照之前的签名算法去生成签名与传过来的
签名进行对比);
2.Sign签名,调用API 时需要对请求参数进行签名验证,签名方式如下:
a. 按照请求参数名称将所有请求参数按照字母先后顺序排序得到:keyvaluekeyvalue…keyvalue 字符串如:将arong=1,mrong=2,crong=3 排序为:arong=1, crong=3,mrong=2 然后将参数名和参数值进行拼接得到参数字符串:arong1crong3mrong2。
b. 将secret加在参数字符串的头部后进行MD5加密 ,加密后的字符串需大写。即得到签名Sign
新api接口代码:
app调用:
http://api.test.com/getproductskey=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35&参数1=value1&参数2=value2…….
注:secret 仅作加密使用, 为了保证数据安全请不要在请求参数中使用。
sign生成的PHP函数:
如上,优化后的请求多了key和sign参数,这样请求的时候就需要合法的key和正确签名sign才可以获取产品数据。这样就解决了身份验证和防止参数篡改问题,如果请求参数被人拿走,没事,他们永远也拿不到secret,因为secret是不传递的。再也无法伪造合法的请求。
但是…这样就够了吗?细心的同学可能会发现,如果我获取了你完整的链接,一直使用你的key和sign和一样的参数不就可以正常获取数据了…-_-!是的,仅仅是如上的优化是不够的
唯一性的实现:在如上的请求参数中,我们加入时间戳:timestamp(yyyyMMddHHmmss),同样,时间戳作为请求参数之一,也加入sign算法中进行加密。
新的api接口:
app调用:
http://api.test.com/getproducts?key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35×tamp=2016032 a604
61407&参数1=value1&参数2=value2…….
如上,我们通过timestamp时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。
Sign签名安全性分析:
通过上面的案例,我们可以看出,安全的关键在于参与签名的secret,整个过程中secret是不参与通信的,所以只要保证secret不泄露,请求就不会被伪造。
总结
上述的Sign签名的方式能够在一定程度上防止信息被篡改和伪造,保障通信的安全,这里使用的是MD5进行加密,当然实际使用中大家可以根据实际需求进行自定义签名算法,比如:RSA,SHA等。
整体思路:
签名基本原理是通过 key/secret 的实现:
1.服务器负责为每个客户端生成一对 key/secret ( key/secret 没有任何关系,不能相互推算),保存,并告知客户端。
2.当客户端调用 api 时,根据某种规则将所有请求参数串联起来并用 secret 生成签名 sign 。
3.将 sign 和 key 一起放进请求参数对服务器进行调用。(注意 secret 不要传)
4.服务端收到请求,根据 key 去查 secret ,然后用同样的算法,验证签名。
5.为避免重放攻击,可加上 timestamp 参数,指明客户端调用的时间。服务端在验证请求时若 timestamp 超过允许误差则直接返回错误。
以上,即使第三方知道了你的算法,key 等信息,由于无法捕获到 secret ,也无法推算,因此是安全的。最好是把 api 布署成 https 的。
参考连接:
http://www.cnblogs.com/codelir/p/5327462.html
http://www.jianshu.com/p/d47da77b6419
对于API安全这块,我们要考虑三个问题:
1.请求参数是否被篡改;
2.请求来源是否合法;
3.请求是否具有唯一性。
为了保证数据在通信时的安全性,我们可以采用参数签名的方式来进行相关验证。
案列分析
我们通过给某 [移动端(app)] 写 [后台接口(api)] 的案例进行分析:
客户端: 以下简称app
后台接口:以下简称api
我们通过app查询产品列表这个操作来进行分析:
app中点击查询按钮->调用api进行查询->返回查询结果->显示在app中
一.不进行验证的方式
api查询接口:app调用:http://api.test.com/getproducts?参数1=value1…….
如上,这种方式简单粗暴,通过调用getproducts方法即可获取产品列表信息了,但是 这样的方式会存在很严重的安全性问题,没有进行任何的验证,大家都可以通过这个方法获取到产品列表,导致产品信息泄露。
那么,如何验证调用者身份呢?如何防止参数被篡改呢?
二.MD5参数签名的方式
我们对api查询产品接口进行优化:1.给app分配对应的key、secret(调用接口的人在在调用的时候就直接把key传过去,但是secret是不能够传递的,但是需要把key放在我们签名中加密,然后在后端,我们接到key之后,就去数据库中查询对应的secrect,然后再按照之前的签名算法去生成签名与传过来的
签名进行对比);
2.Sign签名,调用API 时需要对请求参数进行签名验证,签名方式如下:
a. 按照请求参数名称将所有请求参数按照字母先后顺序排序得到:keyvaluekeyvalue…keyvalue 字符串如:将arong=1,mrong=2,crong=3 排序为:arong=1, crong=3,mrong=2 然后将参数名和参数值进行拼接得到参数字符串:arong1crong3mrong2。
b. 将secret加在参数字符串的头部后进行MD5加密 ,加密后的字符串需大写。即得到签名Sign
新api接口代码:
app调用:
http://api.test.com/getproductskey=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35&参数1=value1&参数2=value2…….
注:secret 仅作加密使用, 为了保证数据安全请不要在请求参数中使用。
sign生成的PHP函数:
public static function sign($appSecret, $params) { if (!is_array($params)) $params = array(); ksort($params); $text = ''; foreach ($params as $k => $v) { $text .= $k . $v; } return md5($appSecret . $text); }
如上,优化后的请求多了key和sign参数,这样请求的时候就需要合法的key和正确签名sign才可以获取产品数据。这样就解决了身份验证和防止参数篡改问题,如果请求参数被人拿走,没事,他们永远也拿不到secret,因为secret是不传递的。再也无法伪造合法的请求。
但是…这样就够了吗?细心的同学可能会发现,如果我获取了你完整的链接,一直使用你的key和sign和一样的参数不就可以正常获取数据了…-_-!是的,仅仅是如上的优化是不够的
三.请求的唯一性:
为了防止别人重复使用请求参数问题,我们需要保证请求的唯一性,就是对应请求只能使用一次,这样就算别人拿走了请求的完整链接也是无效的。唯一性的实现:在如上的请求参数中,我们加入时间戳:timestamp(yyyyMMddHHmmss),同样,时间戳作为请求参数之一,也加入sign算法中进行加密。
新的api接口:
app调用:
http://api.test.com/getproducts?key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35×tamp=2016032 a604
61407&参数1=value1&参数2=value2…….
如上,我们通过timestamp时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。
Sign签名安全性分析:
通过上面的案例,我们可以看出,安全的关键在于参与签名的secret,整个过程中secret是不参与通信的,所以只要保证secret不泄露,请求就不会被伪造。
总结
上述的Sign签名的方式能够在一定程度上防止信息被篡改和伪造,保障通信的安全,这里使用的是MD5进行加密,当然实际使用中大家可以根据实际需求进行自定义签名算法,比如:RSA,SHA等。
整体思路:
签名基本原理是通过 key/secret 的实现:
1.服务器负责为每个客户端生成一对 key/secret ( key/secret 没有任何关系,不能相互推算),保存,并告知客户端。
2.当客户端调用 api 时,根据某种规则将所有请求参数串联起来并用 secret 生成签名 sign 。
3.将 sign 和 key 一起放进请求参数对服务器进行调用。(注意 secret 不要传)
4.服务端收到请求,根据 key 去查 secret ,然后用同样的算法,验证签名。
5.为避免重放攻击,可加上 timestamp 参数,指明客户端调用的时间。服务端在验证请求时若 timestamp 超过允许误差则直接返回错误。
以上,即使第三方知道了你的算法,key 等信息,由于无法捕获到 secret ,也无法推算,因此是安全的。最好是把 api 布署成 https 的。
参考连接:
http://www.cnblogs.com/codelir/p/5327462.html
http://www.jianshu.com/p/d47da77b6419
相关文章推荐
- API接口签名验证2
- API接口签名验证
- 开放api接口签名验证
- 开放api接口签名验证
- 开放API接口签名验证,让你的接口从此不再裸奔
- 开放api接口签名验证
- API接口签名验证
- 简单API接口签名验证
- 开放api接口签名验证
- 开放api接口签名验证
- API接口的签名验证
- 开放api接口签名验证
- android 常用api 接口签名验证
- api 接口的签名验证
- 开放api接口签名验证
- 开放api接口签名验证
- 签名来保证ASP.NET MVC OR WEBAPI的接口安全
- 开放api接口签名验证
- App开放接口api安全性—Token签名sign的设计与实现
- yii2 RESTful 接口 api -3 : 账户验证 和 速度控制