API 接口签名生成及验证

PHP 开发 API 接口签名生成及验证

  • 前言
  • 一、接口签名是什么?
  • 二、设计签名
    • 1.满足条件及注意事项
    • 2.生成签名参数(sing)
    • 签名验证


前言

开发过程中,我们经常会与接口打交道,有的时候是调取别人网站的接口,有的 时候是为他人提供自己网站的接口,但是在这调取的过程中都离不开签名验证。


提示:以下是本篇文章正文内容,下面案例可供参考

一、接口签名是什么?

是为了防止发送的信息被串改,发送方通过将一些字段要素按一定的规则排序后,在转化成json字符串,通过MD5加密机制发送,当接收方接受到请求后需要验证该信息是否被篡改过,也需要将对应的字段按照同样的规则生成验签sign,然后在于接收到的进行比对,可以发现信息是否被串改过。

二、设计签名

1.满足条件及注意事项

可变性:每次的签名必须是不一样的。
时效性:每次请求的时效,过期作废等。
唯一性:每次的签名是唯一的。
完整性:能够对传入数据进行验证,防止篡改。

2.生成签名参数(sing)

第 1 步: 将所有参数(注意是所有参数),除去 sign 本身,以及值是空的参数, 按参数名字母升序排序。

第 2 步: 然后把排序后的参数按参数 1 值 1 参数 2 值 2…参数 n 值 n(这里的参 数和值必须是传输参数的原始值,不能是经过处理的,如不能将"转成”后再拼接) 的方式拼接成一个字符串。

第 3 步: 把分配给接入方的验证密钥 key 拼接在第 2 步得到的字符串前面。

第 4步: 在上一步得到的字符串前面加上验证密钥 key(这里的密钥 key 是接口提供方分配给接口接入方的),然后计算 md5 值,得到 32 位字符串,然后转成大 写.

第 5 步: 计算第 3 步字符串的 md5 值(32 位),然后转成大写,得到的字符串作为 sign 的值。

着急的小伙伴开始催代码了

API 接口签名生成及验证_第1张图片
嘿嘿嘿,没有示例咱也明白不透彻不是?别着急马上就来

举例:
假设传输的数据是
/interface.php?sigin=sign_value&p2=v2&p1=v1&method=cancel&p3=&pn=v(实际情况最好是通过 post 方式发送), 其中 sign 参数对应的 sign_value 就是签名的值。

第一步,拼接字符串,首先去除 sign 参数本身,然后去除值是空的参数 p3,剩 下p2=v2&p1=v1&method=cancel& amp;pn=vn,然后按参数名字符升序排序, method=cancel&p1=v1&p2=v2&pn=vn.

第二步,然后做参数名和值的拼接,最后得到 methodcancelp1v1p2v2pnvn

第三步,在上面拼接得到的字符串前加上验证密钥 key,我们假设是 abc,得到 新的字符串 abcmethodcancelp1v1p2v2pnvn

第四步,然后将这个字符串进行 md5 计算,假设得到的是 abcdef,然后转为大 写,得到 ABCDEF 这个值即为 sign 签名值。

	你是要上天吗,代码呢???

API 接口签名生成及验证_第2张图片

注意,计算 md5 之前请确保接口与接入方的字符串编码一致,如统一使用 utf-8 编码或者 GBK 编码,如果编码方式不一致则计算出来的签名会校验失败。

签名验证

根据前面描述的签名参数 sign 生成的方法规则,计算得到参数的签名值,和参 数中通知过来的 sign 对应的参数值进行对比,如果是一致的,那么就校验通过, 如果不一致,说明参数被修改过。
API 接口签名生成及验证_第3张图片

来了、来了,观众老爷们要的示例代码来了


		// 设置一个公钥(key)和私钥(secret),公钥用于区分用户,私钥加密数据,不能 公开
        $key = "c4ca4238a0b923820dcc509a6f75849b"; 
        $secret = "28c8edde3d61a0411511d3b1866f0636"; 
        // 待发送的数据包 
        $data = array( 
            'username' => '[email protected]',
            'sex' => '1',
            'age' => '16',
            'addr' => 'guangzhou',
            'key' => $key,
            'timestamp' => time(), 
        );
        // 获取 sign 
        function getSign(secret,secret, secret,data) { 
            // 对数组的值按 key 排序 
            ksort($data);// 生成 url 的形式 
            $params = http_build_query($data);// 生成 sign 
            $sign = md5($params . $secret);
            return $sign; 
        }
        // 发送的数据加上 sign 
        data['sign']=getSign(data['sign'] = getSign(data[′sign′]=getSign(secret, $data);
        
        /**
         * 后台验证 sign 是否合法 
         * @param [type] $secret [description] 
         * @param [type] $data [description]
         * @return [type] [description] 
         */
        function verifySign(secret,secret, secret,data) { 
            // 验证参数中是否有签名 
            if (!isset($data['sign']) || !$data['sign']) { 
                echo '发送的数据签名不存在'; die(); 
            }
            if (!isset($data['timestamp']) || !$data['timestamp']) { 
                echo '发送的数据参数不合法'; die(); 
            }
            // 验证请求, 10 分钟失效 
            if (time() - $data['timestamp'] > 600) { 
                echo '验证失效, 请重新发送请求'; die(); 
            }
            $sign = $data['sign'];unset($data['sign']); 
            ksort($data); $params = http_build_query($data);
            // $secret 是通过 key 在 api 的数据库中查询 得到
            $sign2 = md5($params . $secret);
            if ($sign == $sign2) { 
                die('验证通过'); 
            } else { 
                die('请求不合法'); 
            }
        }
?>

以上就是接口签名的内容,感谢各位大佬的阅读、点赞、评论,希望可以帮助到你们。我是 敲码农的小Bug,我们下期见。

你可能感兴趣的:(PHP面试基础篇)