PHP实现API接口签名验证

  • 617

项目需要向外部提供接口,供第三方网站调用,为了保证传输数据的安全性,给项目添加了签名认证的机制,过程大致如下:

一、由我们平台给第三方颁发一个appId和一个appSecret,appId用来传输,appSecret用来生成签名

二、第三方通过拼接appSecret生成签名sign,第三方将数据和appId一起传给我们平台

三、我们平台接收到数据后根据接收到的数据用同样的算法生成签名,通过比对签名确定来进行数据来源的有效性确认

部分代码如下:

一、appId和appSecret的存储表如下:

CREATE TABLE `encrypt` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `public_key` varchar(255) NOT NULL COMMENT '公钥',
  `screct_key` varchar(255) NOT NULL COMMENT '私钥',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4;

二、生成appId和appSecret的方法如下:

/**
     * 生成Key
     * @access public
     * @return array
     */
    public static function makeKey()
    {
        $appId = strrev(microtime(true)*10000);
        $appSecret = md5(md5($appId.'awen').'awen');
        $model = new \common\models\Encrypt();
        $model->public_key = $appId;
        $model->screct_key = $appSecret;
        $model->save();
        return [
            'appId' => $appId,
            'appSecret' => $appSecret,
        ];
    }

三、签名生成方法:

  1. 对所有请求参数进行字典升序排列;
  2. 将以上排序后的参数表进行字符串连接,如key1value1key2value2key3value3...keyNvalueN;
  3. app secret作为后缀,对该字符串进行SHA-1计算,并转换成16进制编码;
  4. 转换为全大写形式后即获得签名串

具体签名生成与对比的代码如下

/**
     * 验证签名有效性
     * @access public
     * @param array params 参数
     * @param sting sign 签名
     * @param sting appId
     * @return bool 验证结果
     */
    public static function checkSign($params,$sign,$appId)
    {
        //根据appId去数据库找到对应的appSecret
        $appSecret = self::getAppSecret($appId);
        // 1. 对加密数组进行字典排序 防止因为参数顺序不一致而导致下面拼接加密不同
        ksort($params);
        // 2. 将Key和Value拼接
        $str = "";
        foreach ($params as $k => $v) {
            $str.= $k.$v;
        }
        //3. 通过sha1加密并转化为大写
        //4. 大写获得签名
        $restr=$str.$appSecret;
        $signRes = strtoupper(sha1($restr));

        if($signRes == $sign){
            return true;
        }else{
            return false;
        }
    }

四、在basecontroller中添加签名验证代码

/**
     * 验证签名
     */
    public function beforeAction($action)
    {
        $post = @file_get_contents('php://input');
        \Yii::$app->log->targets[0]->logFile = \Yii::getAlias('@runtime').DIRECTORY_SEPARATOR.'logs'.DIRECTORY_SEPARATOR.'outside.log';
        \Yii::trace('接受的数据为:'.$post);
        //解析成数组
        $post =  json_decode( $post, true );
        $data = $post['data'];
        if(!$data){
            $result = ['status'=> 0, 'message'=>'缺少参数data'];
            return \Yii::$app->response->data = $result;
        }
        $appId = $post['appId'];
        if(!$appId){
            $result = ['status'=> 0, 'message'=>'缺少参数appId'];
            return \Yii::$app->response->data = $result;
        }
        parse_str($data,$params);
        $sign = $params['sign'];
        unset($params['sign']);
        $signCheck = Encrypt::checkSign($params,$sign,$appId);
        if($signCheck){
            $result = ['status'=> 1, 'message'=>'数据正常','params'=>$params,'appId'=>$appId];
        }else{
            $result = ['status'=> 0, 'message'=>'签名错误','params'=>$params,'appId'=>$appId];
        }

        return \Yii::$app->response->data = $result;
    }

转载:https://blog.csdn.net/weixin_41981080/article/details/105522957

weinxin
我的微信
这是我的微信扫一扫
开拓者博主
  • 本文由 发表于 2021年2月23日19:28:49
  • 转载请务必保留本文链接:https://www.150643.com/555.html
匿名

发表评论

匿名网友 填写信息

评论:1   其中:访客  1   博主  0
    • 雷达探币 雷达探币 3

      挣钱的时候不矫情,花钱的时候不磨叽,好看的时光并不长,奢侈一点又何妨