目录
背景
系统从外部获取数据时,通常采用API接口调用的方式来实现。请求方和接口提供方之间的通信过程,有这几个问题需要考虑:
- 请求参数是否被篡改;
- 请求来源是否合法;
- 请求是否具有唯一性。
今天跟大家探讨一下主流的通信安全解决方案。
参数签名方式
这种方式是主流。它要求调用方按照约定好的算法生成签名字符串,作为请求的一部分,接口提供方验算签名即可知是否合法。步骤通常如下:
- 接口提供方给出
appid
和appsecret
- 调用方根据
appid
和appsecret
以及请求参数,按照一定算法生成签名sign - 接口提供方验证签名
生成签名的步骤如下:
- 将所有业务请求参数按字母先后顺序排序
- 参数名称和参数值链接成一个字符串A
- 在字符串A的首尾加上appsecret组成一个新字符串B
- 对字符串进行md5得到签名sign
假设请求的参数为:f=1,b=23,k=33
,排序后为b=23,f=1,k=33
,参数名和参数值链接后为b23f1k33
,首尾加上appsecret
后md5
:
md5(secretkey1value1key2value2...secret)
。
签名的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 . $appSecret);
}
接口调用方的请求地址类似于:
/api/?f=1&b=23&k=33&sign=signValue
以上签名方法安全有效地解决了参数被篡改和身份验证的问题,如果参数被篡改,没事,因为别人无法知道appsecret
,也就无法重新生成新的sign
。
这里使用了md5
的算法进行签名,也可以自行选择其他签名方式,例如RSA,SHA
等。
唯一性保证
以上方式还不是不够完美的,还是会有小问题如果获取了上面的完整链接,一直使key和sign和一样的参数还是可以正常获取数据的。 因此需要保证“请求的唯一性”。
为了防止别人重复使用请求参数问题,我们需要保证请求的唯一性,就是对应请求只能使用一次,这样就算别人拿走了请求的完整链接也是无效的。唯一性的实现:
在如上的请求参数中,我们加入时间戳 :timestamp(yyyyMMddHHmmss),同样,时间戳作为请求参数之一,也加入sign算法中进行加密。
通过timestamp时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。