前沿
api接口作为越来越常用的东西,我们开放了一个api接口,那么我们必须考虑到安全问题,还有权限问题,只有经过授权的人才可以使用,这里我们就用到了现在最常用的参数签名,下面我们一起来看看吧。
签名的算法
假设参与参数签名计算的请求参数分别是 k1=v1,k2=v2,k3=v3
为了更进一步的安全验证,要求再加一个当前时间的参数,格式为:YYYYMMDDHHIISS。
如:timestamp=20191019152025
将参数键值对以字典序升序排列后,参数和值拼接在一起,即 k1v1k2v2k3v3timestamp20191019152025
将分配的密钥(secret)拼接在最后,假设密钥 secret=abcdefg ,那么最后拼拼接好的字符串为:k1v1k2v2k3v3timestamp20191019152025abcdefg
最后进行md5加密并转为大写,得到的值就是签名的值,即 sign=2102E0C5166ED9857078449572944335
签名计算好后把签名和分配的id连同本来的参数一起传过去就行了,即:
xx.xx?k1=v1&k2=v2&k3=v3×tamp=20191019152025&appid=aa&sign=2102E0C5166ED9857078449572944335
实例 以PHP为例
接口提供方
<?php
/**
* 校验签名
* @param $param array 参数数组
* @param $secret string 密钥
* @return bool
*/
function checkSign($param,$secret){
$sign = $param['sign'];
unset($param['sign']);
ksort($param);
$param_str = '';
foreach ($param as $k => $v){
$param_str .= $k . $v;
}
if (strtoupper(md5($param_str . $secret)) === $sign){
return true;
}
return false;
}
/**
* 校验时间,允许误差为30秒
* @param $timestamp string 参数里的时间字符串
* @return bool
*/
function checkTimestamp($timestamp){
$paramTime = strtotime($timestamp);
$time = time();
$max = $time + 30;
$min = $time - 30;
if ($paramTime <= $max && $paramTime >= $min){
return true;
}
return false;
}
/**
* 校验用户
* @param $appid string 用户的appid
* @return mixed|string
*/
function checkUser($key){
//假设授权了(aa,bb,cc)三位用户,可以使用此接口
$user = [
'aa' => 'asdfghjkl',
'bb' => 'qwertyuiop',
'cc' => 'zxcvbnm',
];
return $user[$key] ?? false;
}
$a = checkUser($_GET['appid']);
$b = checkSign($_GET,$a);
$c = checkTimestamp($_GET['timestamp']);
echo json_encode([
'checkUser' => $a ? true : false,
'checkSign' => $b,
'checkTimestamp' => $c
]);
接口使用方
<?php
const APP_ID = 'aa'; //分配的appid
const SECRET = 'asdfghjkl';//分配的密钥,不当参数传过去
$param = [
'id' => 123,
'name' => '小明',
'age' => 10,
'q' => '1 1',
'appid' => APP_ID,
'timestamp' => date('YmdHis'),
];
$param['sign'] = sign($param,SECRET);
//curl为自己写的curl函数,这里就不写出来了
//说一下参数吧,第一个是地址,第二个是参数数组,第三个是是否post提交,第四个是是否https
$res = curl('localhost/test.php',$param,false,false);
print_r(json_decode($res,true));
/**
* 生成签名
* @param $param array 参数数组
* @param $secret string 访问密钥
* @return string
*/
function sign($param,$secret){
ksort($param);
$param_str = '';
foreach ($param as $k => $v){
$param_str .= $k . $v;
}
return strtoupper(md5($param_str . $secret));
}
运行上面的代码,我们可以看到
Array ( [checkUser] => 1 [checkSign] => 1 [checkTimestamp] => 1 )
