你在写开放的API接口时是如何保证数据的安全性的?先来看看有哪些安全性问题在开放的api接口中,我们通过http Post或者Get方式请求服务器的时候,会面临着许多的安全性问题。
例如:
请求来源和身份是否合法?
请求参数被篡改?
为了保证数据在通信时的安全性,我们可以采用MD5+RSA参数签名的方式来进行相关验证。
依赖js文件:http://www.fores.cc/usr/uploads/2017/08/383667649.zip
前端生成签名
<button id='ajax'>ajax</button>
<div id='text'></div>
<script type="text/javascript">
/*
* 生成签名
* @params 待签名的json数据
* @secret 密钥字符串
*/
function makeSign(params, secret){
var ksort = Object.keys(params).sort();
var str = '';
for(var ki in ksort){
str += ksort[ki] + '=' + params[ksort[ki]] + '&';
}
str += 'secret=' + secret;
var token = hex_md5(str).toUpperCase();
return rsa_sign(token);
}
/*
* rsa加密token
*/
function rsa_sign(token){
var pubkey='-----BEGIN PUBLIC KEY-----';
pubkey+='MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDAbfx4VggVVpcfCjzQ+nEiJ2DL';
pubkey+='nRg3e2QdDf/m/qMvtqXi4xhwvbpHfaX46CzQznU8l9NJtF28pTSZSKnE/791MJfV';
pubkey+='nucVcJcxRAEcpPprb8X3hfdxKEEYjOPAuVseewmO5cM+x7zi9FWbZ89uOp5sxjMn';
pubkey+='lVjDaIczKTRx+7vn2wIDAQAB';
pubkey+='-----END PUBLIC KEY-----';
// 利用公钥加密
var encrypt = new JSEncrypt();
encrypt.setPublicKey(pubkey);
return encrypt.encrypt(token);
}
/*
* 获取时间戳
*/
function get_time(){
var d = new Date();
var time = d.getTime()/1000;
return parseInt(time);
}
//secret密钥
var secret = 'e10adc3949ba59abbe56e057f20f883e';
$("body").on("click","#ajax",function(){
var params = {};
params.name = 'zhansan';
params.age = '30';
params.timestamp = get_time();
params.sign = makeSign(params, secret);
$.ajax({
url : "http://localhost/index1.php",
data : params,
type:'post',
success:function(msg){
$('#text').html(msg);
},
async:false
})
})
</script>
php端校验
<?php
//rsa 私钥
$private_key='-----BEGIN RSA PRIVATE KEY-----
MIICXQIBAAKBgQDAbfx4VggVVpcfCjzQ+nEiJ2DLnRg3e2QdDf/m/qMvtqXi4xhw
vbpHfaX46CzQznU8l9NJtF28pTSZSKnE/791MJfVnucVcJcxRAEcpPprb8X3hfdx
KEEYjOPAuVseewmO5cM+x7zi9FWbZ89uOp5sxjMnlVjDaIczKTRx+7vn2wIDAQAB
AoGAZzUWajxKTZeJqh5FjBgmwZi5M7voFynZAjRWAkCkqZye0FfY7e70kA92C1AL
aVqySnNr4WYZuGorEeOFGqHIv1XSowTLgfLkVBZ/SXiep2QYJrR0YevjysvLnTfb
mrdWCqWSj+0AlQg+AvDA/qtvBVMxKymbpo+4bj5H2pPPZ1ECQQDi1PwJQJBYPbpL
vGmP3AmWg467tCeQ+aJGgtQTOK5BH+p0BWFVDX583R437vllkKI8EXgZfqQfsQcj
7XUAXyZVAkEA2SyFbO8roH9JLrEoxxKGeiGZvhPfNl9nXLhX0OFS0ywQaVBJno39
9W5bX5iP5Jzeb3UWsZ/TxzhGc/b4WjAlbwJBAOFuIn1feRT5Y+hY++BJIg4/+N57
EMd4ENpas0HXFvcKLQvZPP42Rvr5FksoaRuTPmjMQ7uyrJICccI3AAy6g3ECQQDE
AyH9+zRmLNxRj0advsOvUcpgu7DYc21oS12/Qs+tl3TMiNGZkNDphwxjkOA217sP
4B92fCn6AnncSslHJXNzAkBo6ujxqIfrZMOG3ON9nXxkWlq39GFS6CzXWscHA3Xz
FMVT1WWU3FR2Kf2QSKiMGv02YcI2xfowim3JnT6600N0
-----END RSA PRIVATE KEY-----';
//secret密钥
$secret = 'e10adc3949ba59abbe56e057f20f883e';
//私钥解密获取token
openssl_private_decrypt(base64_decode($_POST['sign']), $token, $private_key);
if($token != MakeSign($_POST, $secret)){
exit('token校验失败') ;
}else{
exit('token校验成功');
}
echo date('Y-m-d H:i:s', $_POST['timestamp']);//timestamp参数可以用来验证接口请求时间的有效性
/**
* 生成签名
* 备注:sign不参与签名
* $data # 数组
* $secret # 密钥
*/
function MakeSign($data = '', $secret = '')
{
//签名步骤一:按字典序排序参数
ksort($data);
//签名步骤二:格式化成url参数
$buff = "";
foreach ($data as $k => $v)
{
if($k != "sign"){
$buff .= $k . "=" . $v . "&";
}
}
$string = trim($buff, "&");
//签名步骤三:在string后加入KEY
$string = $string . "&secret=".$secret;
//签名步骤四:MD5加密
$string = md5($string);
//签名步骤五:所有字符转为大写
$result = strtoupper($string);
return $result;
}