看了一篇文章:基于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限制等等。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/227047.html原文链接:https://javaforall.net
