接口的安全校验

目录

背景

系统从外部获取数据时,通常采用API接口调用的方式来实现。请求方和接口提供方之间的通信过程,有这几个问题需要考虑:

  1. 请求参数是否被篡改;
  2. 请求来源是否合法;
  3. 请求是否具有唯一性。

今天跟大家探讨一下主流的通信安全解决方案。


参数签名方式

这种方式是主流。它要求调用方按照约定好的算法生成签名字符串,作为请求的一部分,接口提供方验算签名即可知是否合法。步骤通常如下:

  1. 接口提供方给出appidappsecret
  2. 调用方根据appidappsecret以及请求参数,按照一定算法生成签名sign
  3. 接口提供方验证签名

生成签名的步骤如下:

  1. 将所有业务请求参数按字母先后顺序排序
  2. 参数名称和参数值链接成一个字符串A
  3. 在字符串A的首尾加上appsecret组成一个新字符串B
  4. 对字符串进行md5得到签名sign

假设请求的参数为:f=1,b=23,k=33,排序后为b=23,f=1,k=33,参数名和参数值链接后为b23f1k33,首尾加上appsecretmd5md5(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时间戳用来验证请求是否过期。这样就算被人拿走完整的请求链接也是无效的。