api接口安全验证-传输密文

示意图

 

 

原理

从图中可以看得很清楚,前台想要调用接口,需要使用几个参数生成签名。

时间戳:当前时间

随机数:随机生成的随机数(最好是唯一)

私钥:服务端分配给前端的私钥(附带的还会有一个公钥,公钥作为请求参数传给服务端)

算法规则:商定好的运算规则,利用算法规则生成一个签名。

前台生成一个签名,当需要访问接口的时候,把时间戳,随机数,公钥,请求参数,签名传递到后台。后台拿到这些数据之后,通过一样的算法规则计算出签名,然后和传递过来的签名进行对比,一样的话,返回数据。

算法规则 

签名步骤一:拼接获取到的参数,并按字典序排序参数,得到一个string

签名步骤二:在string后加入KEY=私钥

签名步骤三:MD5加密

签名步骤四:所有字符转为小写

    /**
     * 作用:生成签名
     * @param array $params
     * @return bool
     */
    public function getSign($params = array())
    {
        $private_key = $this->key[$params['public_key']];
        $reqSign = $params['sign'];
        unset($params['sign']);       //sign不参与签名
        unset($params['public_key']); //公钥不参与签名

        //对参数按key,升序排序
        ksort($params, SORT_STRING);
        $queryStr = http_build_query($params);
        $sign = strtolower(md5($queryStr . "&key=" . $private_key));
        if ($reqSign == $sign) {
            return true;
        }

        //兼容rfc 3986 urlencode兼容
        $queryStr = http_build_query($params, '', '&', PHP_QUERY_RFC3986);

        $sign = strtolower(md5($queryStr . "&key=" . $private_key));
        if ($sign == $reqSign) {
            return true;
        } else {
            if (strpos($queryStr, '%28')) {
                $queryStr = str_replace('%28', '(', $queryStr);
            }
            if (strpos($queryStr, '%29')) {
                $queryStr = str_replace('%29', ')', $queryStr);
            }
            if (strpos($queryStr, '%7E')) {
                $queryStr = str_replace('%7E', '~', $queryStr);
            }
            if (strpos($queryStr, '%21')) {
                $queryStr = str_replace('%21', '!', $queryStr);
            }
            if (strpos($queryStr, '%2A')) {
                $queryStr = str_replace('%2A', '*', $queryStr);
            }
            $sign = strtolower(md5($queryStr . "&key=" . self::KEY));
            if ($sign == $reqSign) {
                return true;
            }
        }
        return false;
    }
posted @ 2020-06-12 17:44  晴箜万里  阅读(415)  评论(0编辑  收藏  举报