开放平台api接口签名验证说明

来源:互联网 发布:淘宝嘉年华时间 编辑:程序博客网 时间:2024/05/16 01:32

前言:

在写开放到外部的API接口时是如何保证数据的安全性的?

在外部用户访问开放的api接口中,我们通过http Post或者Get方式请求服务器的时候,

会遇到以下问题:

请求身份是否合法
请求参数是否被篡改
请求的唯一性


为了保证数据在通信时的安全性,我们可以采用参数签名的方式来进行相关验证。

一、示例:
如:客户端client需要调用平台开放api接口进行数据查询

流程其实很简单,不难理解,
client查询==>调用api接口进行查询==>返回查询结果==>显示在client

按照普通未做安全验证的方式就是这样调用:

client调用:

http://ip:port/interfaceName?参数1=value1.......

如上,这种方式简单但是安全问题很大,
通过调用以上链接方式是可以获取产品列表信息了,但是这样的方式会存在很严重的安全性问题,没有进行任何的验证,大家都可以通过这个方法获取到产品列表,导致产品信息泄露;
同时还容易被恶意盗取信息,比如说可以参数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' => '13800138000','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=911091697599……

拼接完后,在最后面再拼接上分配的secret然后用sha对拼接串加密得到签名验证字符串sign,
如:sign=BCC7C71CF93F9CDBDB88671B701D8A35

平台api接口代码:
public Response interfaceName(HttpRequest request){//用户验证,判断key是否存在,并根据key查询出secret用于验证签名//....//验证sign签名,根据前面说的排序等算法把参数进行签名一次得到新的sign和参数中的sign对比//...//查询数据做处理//...return //返回处理结果}

开放api接口签名验证
3.调用

client调用:

http://ip:port/interfaceName?app_key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35&参数1=value1&参数2=value2.......

即:将参数和sign签名一起传到api接口

注:secret 仅作加密使用, 为了保证数据安全请不要在请求参数中使用。


如上,优化后的请求多了key和sign参数,这样请求的时候就需要合法的key和正确签名sign才可以获取产品数据。这样就解决了身份验证和防止参数篡改问题,如果请求参数被人拿走,也拿不到secret,因为secret是不传递的。再也无法伪造合法的请求。

如此便完成了签名接口api调用。

备注:
以上方式还不是不够完美的,还是会有小问题如果获取了上面的完整链接,一直使key和sign和一样的参数还是可以正常获取数据的。
因此需要保证“请求的唯一性”:

为了防止别人重复使用请求参数问题,我们需要保证请求的唯一性,就是对应请求只能使用一次,这样就算别人拿走了请求的完整链接也是无效的。唯一性的实现:在如上的请求参数中,我们加入时间戳 :timestamp(yyyyMMddHHmmss),同样,时间戳作为请求参数之一,也加入sign算法中进行加密。
平台api接口代码:
public Response interfaceName(HttpRequest request){//用户验证,判断key是否存在,并根据key查询出secret用于验证签名//....//验证sign签名,根据前面说的排序等算法把参数进行签名一次得到新的sign和参数中的sign对比//...//验证有效期//...//查询数据做处理//...return //返回处理结果}

开放api接口签名验证

client调用:

http://ip:port/interfaceName?app_key=app_key&sign=BCC7C71CF93F9CDBDB88671B701D8A35×timestamp=201603261407&参数1=value1&参数2=value2.......
如上,我们通过timestamp时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。

关于时间戳验证可以设置单次或者一段时间有效期。









原创粉丝点击