API接口调用鉴权~思考
1.AK/SK(aksk)鉴权
1.1 概述
统一签名认证(ak+sk+时间戳+随机字符串+防重放+防篡改) AK:Access Key Id,用于标示用户。 SK:Secret Access Key,是用户用于加密认证字符串和用来验证认证字符串的密钥,其中SK必须保密。
适用场景:对指定的客户提供接口服务。需要有配套的密钥生成分发系统。客户需要找密钥系统注册提供一些身份信息,用以和生成的密钥做信息绑定(也能方便后期统计接口调用相关信息)。AK当做客户的唯一标识(类似账号),对其他有用参数(包括真正参数,以及时间戳,请求唯一标识等)进行拼接再混合SK,最后进行某种不可逆的摘要算法计算得出一个字符串,作为签名参数一同传递。
1.2 大致流程
- 客户获取AK/SK
客户在配套的系统中注册。申请创建AK/SK,系统生成AK(后期将作为标识,建议使用UUID或其他能确保唯一性的值)以及SK(这个虽然不要求唯一性,但是也是需要有一定复杂度,防止被暴力破解),通过安全的方式传递给客户。同时我们的系统也将存储配套的AK/SK。
- 客户构建请求
客户现在需要调用我们的接口。假设现在和请求业务相关的参数有name=lihua;age=12,构建的请求实际所需要的参数有如下
| |
前两个是业务参数,第三个参数是申请的AK,第三个参数是时间戳,第四个是随机字符串,第6个参数是签名字符串。
之后就是进行签名,计算signature的值v6,一般来说需要对上面有用的参数都需要进行签名。
首先是根据参数名(除了signature签名)进行排序(当然也有其他的排序方式,但是需要提前和服务端沟通,确保验证的时候能同样使用这种方式)
排序之后进行拼接
| |
这时候就需要用到我们同时得到的SK了。也拼接在后面,再进行不可逆摘要算法计算
v6=MD5(TMP+SK)
就得到了signature签名的值
然后就将上面那些参数构建成相应的请求发送给服务端
- 服务端验证请求
首先需要做的就是验证时间戳,通过时间戳判断是否是合法的时间发送的请求,这里需要做的就是比较服务端当前时间和请求中的时间戳是否时间差距过大(这个时间差需要根据情况来设定)。时间戳超时的请求直接返回异常。
然后根据access-key到系统数据库中去找对应的SK,如果不能正常找到,那么就是非法请求,直接异常。能找到的话,服务器就再次根据请求的相关参数进行构建signature,构建出来后和请求中的signature一致就是合法请求,继续业务流程。不一致就是非法请求,直接异常。
1.3 为什么能防止篡改
因为signature的构建是根据请求中的实际参数进行计算得到。同时融入了SK(这个必须要保证保密性,不可外露),所以一旦请求的参数被中途篡改了,签名就会失效,那么就会导致服务端计算的signature和请求中的不一致,会被判定成非法请求。
1.4 为什么能防止重放
参数携带时间戳,请求具有时效性,过期请求会变成非法请求。
同时还有一个 random随机字符串参数,这个在服务端处理的时候,把random放进一个集合中,同时设置一定的过期时间,在验证请求的时候,如果random已经存在,说明已经响应过这个请求,这是就可以直接异常,或者将上一次的缓存的响应结果直接返回。
Java代码实现
| |
2. appID+appKey+appSecret实现权限分配
2.1概述
appID用于标识某个大型应用,appKey+appSecret是成对分配的,一个appID下可以分配多套appKey+appSecret
这里通过appID用于标识应用,下面的可以申请多个appKey,同时对这些不同的appKey配置不同的权限,(某些appKey只能调用GET查询请求,只有高级一点的才能调用其他类型的敏感请求等,具体如何分配权限,根据具体情况设计)
2.2 大致流程
大致流程和上面1AK/SK(aksk)鉴权差不多,只是多了个用于接口验证的参数