重放攻击防御

看了一篇文章:基于timestamp和nonce的防止重放攻击方案,动手用代码实现了一下,感觉还不错。


表单加载

表单加载时执行获取时间戳、随机数、数字签名并发送到客户端:

HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String token = "security.ra.token";
// 使用请求头发送时间戳、随机数、数字签名
ModifyHttpServletRequestWrapper httpServletRequestWrapper = new ModifyHttpServletRequestWrapper(req);
long stime = System.currentTimeMillis();
String nonce = UUID.randomUUID();
String sign = getMD5(token, stime, nonce);//MD5加密(具体方法不再赘述)

httpServletRequestWrapper.putHeader("stime",String.valueOf(stime));// 时间戳
httpServletRequestWrapper.putHeader("nonce", nonce);// 随机数
httpServletRequestWrapper.putHeader("sign", sign);// 数字签名

表单提交

表单提交时验证时间戳、随机数、数字签名:

HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse resp = (HttpServletResponse) response;
String token = "security.ra.token";
//获取客户端提交的隐藏域数据
String stime = req.getParameter("stime");
String nonce = req.getParameter("nonce");
String sign = req.getParameter("sign");
token = getMD5(token, stime, nonce);//获取MD5加密的数字签名(具体方法不再赘述)
long systemTime = System.currentTimeMillis();
try {
	// 这里可优化为提前返回,避免if嵌套,导致代码不美观,可读性差
	if(token.equals(sign)) {//验证签名
		if(systemTime - Long.parseLong(stime) <= 60000) {//验证时间戳,超过60s表示超时
			if(!query(nonce)) {//验证随机数是否已存在,即查询数据库表中是否已含有此随机数,存在则说明已提交
				delete(systemTime );//删除当前时间60s以前存储的数据(具体方法不再赘述)
				add(Long.parseLong(stime), nonce, sign);//增加新的随机数数据(具体方法不再赘述)
				//满足则放行
				...
			}
		}
	}
} catch(Throwable e) {
	//打印日志...
}

对于重放攻击,斯以为这是一种比较好的解决方案,虽然仍可通过模拟客户端的方式模拟正常请求,但成本已成倍增加,得不偿失;另外,也可以考虑使用IP限制等等。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值