如过客户端在向服务端接口进行请求,如果请求信息进行了加密处理,被第三方截取到请求包,虽然第三方无法解密获取其中的数据,但是可以使用该请求包进行重复的请求操作。而使用添加时间戳的方式可以解决这一问题。
正常的HTTP请求,从发出到达服务器一般都不会超过60s,所以服务器收到HTTP请求之后,首先判断时间戳参数与当前时间相比较,是否超过了60s,如果超过了则认为是非法的请求。
直接上代码:
js
在页面引入aes.js,在请求头部中传入加密的时间戳
$.ajax({
cache : true,
type : "post",
headers : {
dateStr : encrypt(new Date().getTime())//加密的时间戳
},
url : "/sysrole/save",
AES前端加密:
function encrypt(value) {
//密钥
var secretKey = CryptoJS.enc.Utf8.parse("asdfghjk18537gbe");
var srcs = CryptoJS.enc.Utf8.parse(data);
//加密
var encrypted = CryptoJS.AES.encrypt(srcs, secretKey, {
mode : CryptoJS.mode.ECB,
padding : CryptoJS.pad.Pkcs7
});
return encrypted.toString();
}
定义一个过滤器在doFilter方法中加入下面代码。自定义定义过滤器可以在网上找:
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain) throws IOException, ServletException {
HttpServletRequest request1 = (HttpServletRequest) request;
String s = request1.getRequestURI();
logger.info("请求URL:"+s);
if (s.contains("/save")){
//获取到加密的时间戳
String dateStr = request1.getHeader("dateStr");
//解密时间戳
String decrypted = decrypt(dateStr);
if(StringUtils.isBlank(dateStr) || StringUtils.isBlank(decrypted)){
logger.info("请求参数错误");
return;
}
//一般抓包攻击请求时间都大于60秒,所以超过60秒拦截
if(difference(new Date(), decrypted) > 60){
logger.info("请求超时");
return;
}
}
}
在Java世界中,AES、DES加密解密需要使用Cipher对象构建加密解密系统,Hutool中对这一对象做再包装,简化了加密解密过程
引入Hutool:
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>4.1.2</version>
</dependency>
解密字符串:
public static String decrypt(String encryptHex){
//密钥 必须与前端js的相同
String key = "wertgbyhnufbge74";
//构建
AES aes = SecureUtil.aes(key.getBytes());
//解密为原字符串
return aes.decryptStrFromBase64(encryptHex);
}
public int difference(Date nowDate, String decrypted){
return Math.abs((int)(nowDate.getTime()-Long.valueOf(decrypted))/1000);
}