项目中常用的API接口签名验证方法:
1.给app分配对应的appId、appKey 2. Sign签名,调用API 时需要对请求参数进行签名验证,签名方式如下:
a. 按照请求参数名称将所有请求参数按照键名进行升序排序,如:将arong=1,mrong=2,crong=3 排序为:arong=1, crong=3,mrong=2 然后将参数名和参数值进行拼接得到参数字符串:arong=1&crong=3&mrong=2
b. 将appKey加在参数字符串的尾部&key=appKey后进行MD5加密 ,加密后的字符串需转小写。即得到签名Sign;
php签名类
<?php
/**
* Created by PhpStorm.
* User: Pasa吴
* Date: 2023/1/2
* Time: 21:29
*/
namespace utils;
/**
* 签名校验
* Class Sign
* @package utils
*/
class Sign
{
private $appId = "2jOlqkesGGeJJwMx";
private $appKey = "wfEj1kXLdKjCV6rla6Rfasd";
//创建sign
public function makeSign($data)
{
ksort($data);
$string = $this->toUrlParams($data);
$string = $string . "&key=" . $this->appKey;
$string = md5($string);
$result = strtolower($string);
return $result;
}
//检验sign是否正确
public function verifySign($data)
{
//check sign
if (!isset($data['sign']) || !$data['sign']) {
return ['code' => 1, 'msg' => '发送的数据签名sign不存在'];
}
//check sign
if (!isset($data['appid']) || !$data['appid']) {
return ['code' => 1, 'msg' => '发送的应用参数appid不存在'];
}
if ($data['appid'] != $this->appId) {
return ['code' => 1, 'msg' => '发送的应用参数appid错误'];
}
//check sign
if (!isset($data['nonce']) || !$data['nonce']) {
return ['code' => 1, 'msg' => '发送的应用参数nonce不存在'];
}
//check timestamp
if (!isset($data['timestamp']) || !$data['timestamp']) {
return ['code' => 1, 'msg' => '发送的数据参数timestamp不合法'];
}
// 验证请求, 10分钟失效
if (time() - $data['timestamp'] > 600) {
return ['code' => 1, 'msg' => '验证超时timestamp请重新发送请求'];
}
$clientSign = $data['sign'];
unset($data['sign']);
$serverSign = $this->makeSign($data);
if ($clientSign == $serverSign) {
return ['code' => 0, 'msg' => '验证通过'];
} else {
return ['code' => 1, 'msg' => '签名校验失败'];
}
}
//生成url字符串
private function toUrlParams($values)
{
$buff = "";
foreach ($values as $k => $v) {
if ($k != "sign" && !is_array($v)) {
$buff .= $k . "=" . $v . "&";
}
}
$buff = trim($buff, "&");
return $buff;
}
}
使用实例,签名校验可以写在中间件拦截
<?php
/**
* Created by PhpStorm.
* User: Pasa吴
* Date: 2023/1/2
* Time: 21:29
*/
namespace app\api\controller;
use think\facade\Request;
use utils\Sign;
class Test
{
public function sign(Request $request)
{
//接口签名校验
$appid = $request->header('appid', '');
$nonce = $request->header('nonce', '');
$timestamp = $request->header('timestamp', '');
$sign = $request->header('sign', '');
/* @var Sign $Sign */
$Sign = app(Sign::class);
$verifySign = $Sign->verifySign(compact('appid', 'nonce', 'timestamp', 'sign'));
if (isset($verifySign['code']) && $verifySign['code']) {
throw new IllegalException();
}
}
}
前端vue代码
<div id="app">
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
<script type="text/javascript">
new Vue({
el: '#app',
data() {
return {
info: null
}
},
create(){
},
methods: {
getSign: function(param,key) {
let str = "";
for(var idx in param) {
let one = idx+"="+param[idx];
if (str == "") {
str = one;
} else {
str = str+"&"+one;
}
}
str = str+"&key="+key;
//console.log("before md5:"+str);
let md5str = md5(str);
return md5str;
}
},
mounted() {
let appid = "2jOlqkesGGeJJwMx";
let appkey = "wfEj1kXLdKjCV6rla6Rfasd";
let timestamp = parseInt((new Date()).getTime()/1000);
let nonce = Math.floor(Math.random()*8999)+1000;
let param = {
appid:appid,
nonce:nonce,
timestamp:timestamp,
}
let sign = this.getSign(param,appkey);
param.sign = sign;
console.log(param);
const config = {
headers: {
appid: param.appid,
nonce: param.nonce,
timestamp: param.timestamp,
sign:param.sign,
}
};
axios
.post('https://www.baidu.com/api/Test/sign',[],config)
.then(response => (this.info = response))
.catch(function (error) { // 请求失败处理
console.log(error);
});
}
})
</script>
本文为Pasa吴原创文章,转载无需和我联系,但请注明来自Pasa吴博客https://www.pasawu.top
最新评论