开发的项目中可能会出现下面这些情况:
- 由于用户误操作,多次点击表单提交按钮。
- 由于网速等原因造成页面卡顿,用户重复刷新提交页面。
- 黑客或恶意用户使用postman等工具重复恶意提交表单(攻击网站)。
这些情况都会导致表单重复提交,造成数据重复,增加服务器负载,严重甚至会造成服务器宕机。因此有效防止表单重复提交有一定的必要性。
解决方案:
一、 使用一个token(令牌)的机制- 服务器在处理请求之前先来检查浏览器的token
- token由服务器来创建,并交给浏览器,浏览器在向服务器发送请求时需要带着这个token
- 服务器处理请求前检查token是否正确,如果正确,则正常处理,否则返回一个错误页面
- 服务器所创建的token只能使用一次
- token一般使用一个唯一的标识
案例:
在jsp页面,获取UUID作为token
UUID:32位字符串,通常作为对象或者表的唯一标识,根据机器码和时间戳(从1970年1月1日开始到现在)生成。
登录页面
用户名:
密 码:
记住我一周
${errorMsg }
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
req.setCharacterEncoding("utf-8");
resp.setCharacterEncoding("utf-8");
//获得登录的账号和密码
String username = req.getParameter("username");
String password = req.getParameter("password");
String token = req.getParameter("token");
HttpSession session = req.getSession();
String sessionUUID = (String) session.getAttribute("uuid");
//检查token
if(sessionUUID.equals(token)) {
if(username.equals("admin") && password.equals("admin123")){//登录成功
//重定向到index.jsp
resp.sendRedirect(req.getContextPath() +"/index.jsp");
}else{//登录失败
req.setAttribute("errorMsg", "用户名或密码不正确");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}else {
req.setAttribute("errorMsg", "重复登录");
req.getRequestDispatcher("/login.jsp").forward(req, resp);
}
}
二、通过JavaScript屏蔽提交按钮
通过js代码,当用户点击提交按钮后,屏蔽提交按钮使用户无法点击提交按钮或点击无效,从而实现防止表单重复提交。
ps:js代码很容易被绕过。比如用户通过刷新页面方式,或使用postman等工具绕过前段页面仍能重复提交表单。因此不推荐此方法。
登录页面
用户名:
密 码:
记住我一周
${errorMsg }
$(function(){
var submitbtn = $("#submitbtn");
$("#submitbtn").on("click", function(){
//this.disabled=true;
$("#submitbtn").attr('disabled',true);;
this.parentNode.submit();
});
});
简单的防表单重复提交,做一整理,可根据框架来具体实现