开放平台api接⼝签名验证说明
前⾔:
在写开放到外部的API接⼝时是如何保证数据的安全性的?
在外部⽤户访问开放的api接⼝中,我们通过http Post或者Get⽅式请求服务器的时候,
会遇到以下问题:
请求⾝份是否合法
请求参数是否被篡改
请求的唯⼀性
为了保证数据在通信时的安全性,我们可以采⽤参数签名的⽅式来进⾏相关验证。
⼀、⽰例:
如:客户端client需要调⽤平台开放api接⼝进⾏数据查询
流程其实很简单,不难理解,
client查询==>调⽤api接⼝进⾏查询==>返回查询结果==>显⽰在client
按照普通未做安全验证的⽅式就是这样调⽤:
client调⽤:
如上,这种⽅式简单但是安全问题很⼤,
通过调⽤以上链接⽅式是可以获取产品列表信息了,但是这样的⽅式会存在很严重的安全性问题,没有进⾏任何的验证,⼤家都可以通过这个⽅法获取到产品列表,导致产品信息泄露;
同时还容易被恶意盗取信息,⽐如说可以参数1的值改成1,2,3,4...不断的去类似“撞库”去调⽤。
⼆、使⽤数据签名(使⽤sha或者Md5,获取其它算法)
针对以上问题,我们对开放平台的api接⼝进⾏优化:
1.给每个客户端client分配对应的key、secret,可以理解成:⽤户名密码;
2.Sign签名:调⽤API时需要对请求参数进⾏签名验证,签名⽅式如下:
a. 按照请求参数名称将所有请求参数按照字母先后顺序排序(如果参数层次⽐较多可以只做⼀级排序),
$param = array(
'access_token' => '',
'app_key' => '152968d9af768bf084dad750f78d6866',
'client' => '{"channel":"mcontact_md_ahlrj_api_android","imei":"1","version":"v3.9.8"}',
'once' => '911091697599',
'phone' => '138********',
'sdk_from' => 'java',
'type' => 0,
'version' => '1.0',
);
b.然后将参数名和参数值进⾏拼接得到参数字符串,如:
access_token=app_key=152968d9af768bf084dad750f78d6866client={"channel":"mcontact_md_ahlrj_api_android","imei":"1","version":"v3.9.8"}once=9110
拼接完后,在最后⾯再拼接上分配的secret然后⽤sha对拼接串加密得到签名验证字符串sign,
如:sign=BCC7C71CF93F9CDBDB88671B701D8A35
平台api接⼝代码:
public Response interfaceName(HttpRequest request){
//⽤户验证,判断key是否存在,并根据key查询出secret⽤于验证签名
//....
//验证sign签名,根据前⾯说的排序等算法把参数进⾏签名⼀次得到新的sign和参数中的sign对⽐
//...
//查询数据做处理
//...
return //返回处理结果
}
开放api接⼝签名验证
3.调⽤
client调⽤:
ip:port/interfaceName?app_key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35&参数1=value1&参数
即:将参数和sign签名⼀起传到api接⼝
注:secret 仅作加密使⽤, 为了保证数据安全请不要在请求参数中使⽤。
如上,优化后的请求多了key和sign参数,这样请求的时候就需要合法的key和正确签名sign才可以获取产品数据。这样就解决了⾝份验证和防⽌参数篡改问题,如果请求参数被⼈拿⾛,也拿不到secret,因
为secret是不传递的。再也⽆法伪造合法的请求。
如此便完成了签名接⼝api调⽤。
备注:
以上⽅式还不是不够完美的,还是会有⼩问题如果获取了上⾯的完整链接,⼀直使key和sign和⼀样的参数还是可以正常获取数据的。
因此需要保证“请求的唯⼀性”:
为了防⽌别⼈重复使⽤请求参数问题,我们需要保证请求的唯⼀性,就是对应请求只能使⽤⼀次,这样就算别⼈拿⾛了请求的完整链接也是⽆效的。唯⼀性的实现:在如上的请求参数中,我们加⼊时间戳 :timestamp(yyyyMMddHHmmss),同样,时间戳作为请求参数之⼀,也加⼊sign算法中进⾏加密。
平台api接⼝代码:百度api接口
public Response interfaceName(HttpRequest request){
//⽤户验证,判断key是否存在,并根据key查询出secret⽤于验证签名
/
/....
//验证sign签名,根据前⾯说的排序等算法把参数进⾏签名⼀次得到新的sign和参数中的sign对⽐
//...
//验证有效期
//...
//查询数据做处理
//...
return //返回处理结果
}
开放api接⼝签名验证
client调⽤:
ip:port/interfaceName?app_key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35×timestamp=201603261407&参数1=value1&参数
如上,我们通过timestamp时间戳⽤来验证请求是否过期。这样就算被⼈拿⾛完整的请求链接也是⽆效的。
关于时间戳验证可以设置单次或者⼀段时间有效期。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论