java Web防止表单重复提交危害及解决方案 token机制详解
token机制详解
注:文内关于使用验证码图片的代码请参考我的另一篇博客
java Web项目中导入验证码图片功能步骤详解
重复提交的危害
1)数据库可能会多次保存相同数据
2)安全问题,如多次支付等
3)服务器性能受损
重复提交的几种情况
1)成功提交后,直接刷新页面(每一次刷新就是重复上一次请求)
解决方案:将转发改为重定向即可
2)由于网速或服务器的性能,导致处理请求满,用户重复点击注册等提交表单按钮
解决方案:将提交按钮点击后设为不可用。然后手动提交表单
js页面代码:
<script type="text/javascript">
window.onload=function(){
var btn=document.getElementById("subId");
btn.onclick=function(){
//将按钮设为不可点后 提交表单的动作被覆盖了
//所以我们需要手动提交表单
this.disabled=true;
//提交表单
var formEle=doucument.getElementById("form");
formEle.submit();
};
};
</script>
3)用户点击后退按钮,再次提交
解决方案:由于http为无状态协议,浏览器无法分辨提交的请求是否上次已经提交过,所以我们在这里引入token的概念,通过token来判断是否重复提交
每次提交表单,带上token令牌,服务器验证口令是否和我们在session域中取出的一致,一致则为合法请求,不一致则打回请求
3.1)在session域中设置uuid
<%
//产生一个唯一不重复的令牌当作token
String uuid= UUID.randomUUID().toString();
//放入session域中方便服务器验证
session.setAttribute("token", uuid);
%>
3.2)在表单提交时带上值为uuid的token参数
<form action="login" id="form">
<label>用户名称:</label>
<input type="text" name="username" value="">
<br> <br>
<label>用户密码:</label>
<input type="password" name="pwd" value="">
<br> <br>
<label>验证码:</label>
<input type="text" style="width: 120px;" name="code"/>
<img alt="" src="code.jpg" height="29px" width="70px" id="codeImg">
<input type="text" name="token" value=<%=uuid %>>
<input type="submit" value="登录" id="subId">
</form>
3.3)在servlet中接受用户提交时取出session域中存放的token和表单中带来的token
String token=request.getParameter("token");
HttpSession session = request.getSession();
String tokenSession = (String) session.getAttribute("token");
//从session中取出token后将域中token重新赋值
session.setAttribute("token", UUID.randomUUID().toString());
if(token.equals(tokenSession)) {
//token相同 合法请求
}else {
//token不相同,打回请求
}
3.3)关于为什么这样编写后可以防止用户返回后重新提交及为何要重新设置session域中token值详解
用户第一次点击登录,session域和表单提交带上的token是相同的,servlet接收到请求后会对两者取出的token进行比较,成功则继续请求,反之打回请求。
不管成功与否,服务器都会将session域中的token重新设置,而当用户返回后重新提交,表单中token的值是在缓存中取出的,而session域中的token已经是在servlet中被重新赋值了的,两个自然不同,请求被认定为非法请求,直接打回
仅在学习过程中记录所学内容,如有何处不足还请大佬们指出,欢迎同行一起交流。联系我微信chenhan-wu,记得备注csdn
上一篇: 配置storm
下一篇: CMake 实践与踩坑记录(三)