项目需要向外部提供接口,供第三方网站调用,为了保证传输数据的安全性,给项目添加了签名认证的机制,过程大致如下:
一、由我们平台给第三方颁发一个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;
}
本文介绍了一种用于确保第三方调用接口时数据安全性的签名认证机制。平台为第三方颁发appId和appSecret,第三方使用appSecret生成签名,平台通过对比签名验证数据有效性。
4232

被折叠的 条评论
为什么被折叠?



