防止表达重复提交
-
问题:什么是表单重复提交?
- 当在注册或者登陆遇到网络卡顿或者页面不能正常刷新时,我们大多数人都会进行对此的刷新操作;
- 如果不进行表单重复提交的处理会带来很大的危害
- 表单重复提交 危害: 刷票、 重复注册、带来服务器访问压力(拒绝服务)
-
解决方案:
- 在页面上生成一个令牌(就是一个随机字符串UUID),将其存储到session中,并在表单中携带.
- 在服务器端,获取数据时,也将令牌获取,将它与session中存储的token对比,没问题,
- 将session中令牌删除。
Servelt的防止表单重复提交
在Register.jsp页面随机生成令牌,并将其带到服务器端
Register.jsp
<body>
<!-- 生成随机的令牌 -->
<%
String token = UUID.randomUUID().toString();
session.setAttribute("token", token);
%>
<form action="${pageContext.request.contextPath }/register" method="get" >
<input type="hidden" name="token" value="<%=token%>" />
username:<input type="text" name="username" /><br>
password:<input type="password" name="password" /><br>
<input type="submit" value="注册"/>
</form>
</html>
RegisterServlet.java服务器端进行处理:
@WebServlet("/register")
public class RegisterServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
// 取出参数中的令牌和在session中的进行对比
String token = request.getParameter("token");
String _token = (String) request.getSession().getAttribute("token");
// 移除令牌
request.getSession().removeAttribute("token");
if (token.equals(_token)) {
System.out.println("将" + username + " 与" + password + "存储到数据库中,完成注册");
} else {
response.getWriter().write("不允许表单重复提交");
}
}
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doGet(request, response);
}
}
Struts2的表单重复提交
struts2中怎样解决表单重复提交:
-
在struts2中解决表单重复提交,可以使用它定义的一个interceptor。
<interceptor name="token" class="org.apache.struts2.interceptor.TokenInterceptor"/>
-
步骤:
-
在页面上需要使用一个token tag
在表单中添加一个标签 <s:token/>
就会在页面上生成一个令牌,并存在于表单中。
-
需要在action中引入token拦截器
同时引入默认的拦截器栈(defaultStack)或者最基本的拦截器栈(basicStack)
<interceptor-ref name=“token”/>
-
在重复提交时会报错,我们需要对错误进行配置和显示
- 在struts.xml中配置invalid.token结果视图
<!-- 可以选择将其重返注册页面 --> <result name="invalid.token">/Struts2_Register.jsp</result>
-
在jsp页面使用标签进行错误的显示:
<s:actionerror/>
-
在显示的错误信息时将其国际化
在struts2-core-2.3.33.jar的org.apache.struts2包下的struts-messages.properties文件中有一个常量struts.messages.invalid.token是用来显示错误的
在同action下创建同名的配置文件ActionClassName.properties
struts.messages.invalid.token=禁止表单重复提交
-
-
Struts2_Register.jsp页面:
<%@page import="java.util.UUID"%> <%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <%@taglib prefix="s" uri="/struts-tags" %> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Insert title here</title> </head> <body> <s:actionerror/> <form action="${pageContext.request.contextPath }/register" method="get"> <s:token/> username:<input type="text" name="username" /><br> password:<input type="password" name="password" /><br> <input type="submit" value="注册" /> </form> </html>
RegisterAction.java
package com.syj.action; import com.opensymphony.xwork2.ActionSupport; public class RegisterAction extends ActionSupport { private String username; private String password; public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @Override public String execute() throws Exception { System.out.println("将" + username + " 与" + password + "存储到数据库中,完成注册"); return null; } }
struts.xml配置
<struts> <package name="p1" extends="struts-default" namespace="/"> <action name="register" class="com.syj.action.RegisterAction"> <interceptor-ref name="token" /> <interceptor-ref name="defaultStack" /> <!-- 可以选择将其重返注册页面 --> <result name="invalid.token">/Struts2_Register.jsp</result> </action> </package> </struts>