PHP前后端分离,数据防篡改解决方案
在前后端分数据传输中,经常需要考虑数据安全问题,确保数据不被篡改,最近正好做的项目有所涉及,记录一下前后端数据加密过程
1.前端使用layui-vue,在http拦截器中统一加入数据加密逻辑
/**
* 需要加签、验签的路径集合
* 例:"/user",将匹配以"/user"开头的所有API
*/
const blackBeginUrl = ["/login", "/role", '/admin']
class Http {
service;
constructor(config: TAxiosOption) {
this.service = axios.create(config)
/* 请求拦截 */
this.service.interceptors.request.use((config: InternalAxiosRequestConfig) => {
const userInfoStore = useUserStore();
if (userInfoStore.token) {
(config.headers as AxiosRequestHeaders).token = userInfoStore.token as string
} else {
if(router.currentRoute.value.path!=='/login') {
router.push('/login');
}
}
// 数据加密过程
let needSign = false;
for (let blackUrl of blackBeginUrl) {
// @ts-ignore
if (config.url.indexOf(blackUrl) != -1) {
needSign = true;
break;
}
}
if(needSign){
// 这里默认post请求的Content-Type:application/json
let requestData = "";
console.log(config.method)
if (config.method === "get") {
requestData = config.params
} else if (config.method == "post") {
requestData = config.data
}
// 时间戳,作为slat的必备组成之一
const timestamp = new Date().getTime().toString();
config.headers['Timestamp'] = timestamp
// 随机字符串,作为slat的必备组成之一
const randomStr = "K:*C8bw6zJ"
// slat = 时间戳 + 随机字符串 (自定义slat公式)
const slat = timestamp.concat('', randomStr);
const signature = CryptoHmacSha1(JSON.stringify(requestData), slat);
config.headers['Signature'] = signature;
}
return config
}, error => {
return Promise.reject(error);
})
2.后端使用的是Thinkphp6框架,在中间件中加入数据解密逻辑
<?php
declare (strict_types = 1);
namespace app\middleware;
use response\ApiCode;
class CheckRequestMiddleware
{
/**
* 处理后台接口签名
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
//验证请求头时间
$timestamp = $request->header('Timestamp');
$serTimestamp = time() * 1000;
if($timestamp - $serTimestamp > 60 * 1000){
//签名时间戳过期,返回提示信息
return json(['code' => ApiCode::CODE_ERROR, 'data'=>[], 'msg'=> ApiCode::msg['CODE_ERROR']]);
}
//验证签名
$signature = $request->header('Signature');
if($signature){
$params = $request->param();
$randomStr = env('signature.random');
$salt = $timestamp . $randomStr;
//生成临时签名验证
$temSignature = hash_hmac('sha1', json_encode($params, JSON_UNESCAPED_UNICODE), $salt);
if($temSignature !== $signature){
//数据签名验证失败,可能被篡改,返回提示信息
return json(['code' => ApiCode::SIGN_ERROR, 'data'=>[], 'msg'=> ApiCode::msg['SIGN_ERROR']]);
}
}
//数据签名验证通过,继续处理请求
return $next($request);
}
}
3.模拟请求,查看效果
收到1条评论
Risin9 2024-06-18 10:29
写的很好
回复