API安全
数据准备
header:
time:时间戳
token:用户登录信息token jwt
version:版本
did:设备号
......
body:
name:gaozhan
......
客户端加密
1.生成随机AES加密字符串aes_key
2.aes_key对header内容加密 aes_header
3.aes_key对body内容加密 aes_body
4.rsa公钥对aes_key进行加密 rsa_aes_key
传输
0.rsa_aes_key放入header
1.aes_header放入header
2.aes_body 放body
服务端解密
0.RSA私钥对rsa_aes_key解密 得到aes_key
1.aes_key对header解密
2.校验时间戳时效性/版本有效性/用户访问权限
3.aes_key对aes_body解密
代码示例
github: https://github.com/gaozhan3253/app-restful-api-demo
片段
laravel中间件:
//获取rsa_aes_key
$rsa_aes_key=$request->header('rsa-aes-key');
//不存在rsa加密字符串时
if(empty($rsa_aes_key)) {
return response()->json(['message'=>'非法访问','status_code'=>401],401);
}
//解密rsa加密字符串 得到aes加密字符串
$aes_key= RsaOptions::decrypt($rsa_aes_key);
if(empty($aes_key)) {
return response()->json(['message'=>'非法访问','status_code'=>401],401);
}
//接收aes加密的header
$aes_header=$request->header('aes-header');
if(empty($aes_header)) {
return response()->json(['message'=>'无加密header信息','status_code'=>401],401);
}
//解密aes加密字符串
$headers= AesOptions::aes128cbcDecrypt($aes_header,$aes_key);
$headers=json_decode($headers);
//验证是否存在必须time字段 因为time字段绝对存在
if(empty($headers) ||empty($headers->time)) {
return response()->json(['message'=>'无效header','status_code'=>401],401);
}
//验证唯一性
$onlyToken=$headers->onlytoken;
//$onlyToken=$headers->onlytoken.rand(000001,999999);//测试用 唯一性处理
$onlyTokenHasBool= Cache::store('redis')->has($onlyToken);
if($onlyTokenHasBool) {
return response()->json(['message'=>'重复请求','status_code'=>401],401);
}else{
Cache::store('file')->put($onlyToken,'',5);
}
//验证时效性
$requestTime=$headers->time;//请求的时间戳
$expiresTime=strtotime('-'. env('API_EXPIRES_TIME',1) .' minute');//请求有效时间
if($expiresTime>$requestTime) {
return response()->json(['message'=>'请求已过期','status_code'=>401],401);
}
//将aes_key保存 用于将返回信息加密
define('AES_KEY',$aes_key);
//将解密后的header写回header中
if(count($headers)){
foreach($headers as $key=>$value){
//jwt验证token格式化处理
if($key=='token'){
$key='authorization';
$value='bearer '.$value;
}
$request->headers->set($key,$value);
}
}
//获取body
$aes_body=$request->get('aes-body','');
//解密aes加密字符串
$bodys= AesOptions::aes128cbcDecrypt($aes_body,$aes_key);
$bodys=json_decode($bodys);
if(count($bodys)){
foreach($bodys as $key=>$value){
$request->offsetSet($key,$value);
}
}