开放接口签名验证

php
jiang 发表于2020-09-10 13:26:57 最后修改于2025-03-14 06:55:37 4147

开放接口签名验证

接口安全问题

  • 请求身份是否合法?
  • 请求参数是否别篡改?
  • 请求是否唯一?

AccessKey和SecretKey签名验证

为开发者分配AccessKey(开发者标识,确保唯一) SecretKey(用于接口加密,确保不易被穷举,生成算法不易被猜测)

防止篡改

参数签名防止篡改

  • 按照要求将参数名的字母升序倒序非空请求参数(该参数包含AccessKEy)使用URL键值对格式(key1=value1&key2=value2&...)拼接成字符串stringA
  • 在stringA后再拼接上SecretKey的得到StringSignTemp
  • 对StringSignTemp进行MD5运算,并将得到的字符串转为大写得到sign字符串
  • 请求携带参数AccessKey和Sign,只有拥有合法身份的AccessKey和正确的签名sign才能放行。 以上解决了参数篡改问题。即使参数被劫持,由于获取不到SecretKey(SecretKey仅做本地加密用,不参与网络传输),无法伪造请求。

重放攻击

虽然解决了请求参数篡改的问题,但是存在重复请求的可能。

timestamp + nocne 防止重放攻击

nonce指唯一的随机字符串,用来标识每个签名的请求。通过为每个请求提供唯一的标识,服务器可以记录标识防止标识被多次使用。
但是记录每一个标识显得代价很大。可以使用timestamp优化nonce的存储,允许10分钟之内的请求进入。
首先,检查timestamp是否在10分钟之内,超过时间则拒绝。如果在10分钟以内则继续检查nonce是否存在,若存在则拒绝,否则记录当前的nonce然后删除过期的nonce,并认为当前请求合法。(因为防止了篡改所以timestamp和nonce无法更改。)

实现

请求接口 http://api.test.cn/test?name=jo&home=word

客服端

  • 生成当前的时间戳和唯一随机字符串:timestamp=now&nonce=random
  • 按照请求参数的字母升序排列请求参数:stringA=Accesskey=accesskey&home=word&name=jo
  • 再拼接上timestamp=now&nonce=random还有SecretKey得到stringSignTemp=Accesskey=accesskey&home=word&name=jo&timestamp=now&nonce=random&SecretKey=secretkey
  • 最后将stringSignTemp加密signstring=MD5(stringSignTemp),也可以转为大写
  • 最后转化为http://api.test.cn/test?name=jo&home=word&timestamp=now&nonce=random&sign=signstring

服务端

  • 第一步检查timestamp是否过时,过时则返回错误
  • 第二步检查nonce是否存在,存在则返回错误
  • 第三步检查,按参数排序(这里的参数排除了timestamp和nonce以及SecretKey)后的Accesskey=accesskey&home=word&name=jo字符串,再拼接一次Accesskey=accesskey&home=word&name=jo&timestamp=now&nonce=random&SecretKey=secretkey再对其进行MD5得到字符串A
  • 将sign和A对比,如果相同则请求正确,没有被篡改,且请求是唯一的,存nonce并删除过期的nonce,如果不同则返回错误。

Token和AppKey签名验证

和上面相同,把AccessKey换成Token再把SecretKey换成AppKey。


小提示 now
头像
这里还没有评论,快评论吧。
头像

jiang

积土而为山,积水而为海。

Copyright © 2017-2020 嘉丽谷 版权所有