- 问题:使用forward转发请求后,再次刷新当前页面,会进行重复提交;
- 例子:使用LoginServlet进行登录,成功后跳转到login页面,刷新当前页面,再次直接进行了登录;如果这是支付、买票等页面,重复提交将导致严重后果。因此要解决重复提交的问题。
- 为了能够解决重复提交问题,关键在于:能够标志一次提交,从而识别出该提交已经处理。下面是主要处理过程:
<form action="login" method="post">
<input type="hidden" name="ANTI_DUPLICATE_SUBMIT_TOKEN" value="${ANTI_DUPLICATE_SUBMIT_TOKEN}"/>
<input type="text" name="username" />
<br/>
<input type="password" name="password" />
<br/>
<input type="submit"/>
</form>
@WebServlet("/login")
public class LoginServlet extends HttpServlet {
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
String username = request.getParameter("username");
String password = request.getParameter("password");
System.out.println(username);
response.getWriter().println(username + " : "+password);
}
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
doPost(request, response);
}
}
public class RandomUtil {
private static final String SRC="1234567890QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm";
public static String randomChars(int x){
StringBuilder sb = new StringBuilder();
for(int i=0;i<x;i++){
sb.append(SRC.charAt(new Random().nextInt(SRC.length())));
}
System.out.println(sb.toString());
return sb.toString();
}
}
@WebFilter("/*")
public class AntiDuplicateSubmissionFilter implements Filter {
public void destroy() { }
public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain) throws ServletException, IOException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) resp;
String reqToken = request.getParameter("ANTI_DUPLICATE_SUBMIT_TOKEN");
if (reqToken==null || reqToken.isEmpty()){
String token = RandomUtil.randomChars(32);
request.getSession().setAttribute("ANTI_DUPLICATE_SUBMIT_TOKEN",token);
}else {
Object sessionToken = request.getSession().getAttribute("ANTI_DUPLICATE_SUBMIT_TOKEN");
if (reqToken.equals(sessionToken)){
String token = RandomUtil.randomChars(32);
request.getSession().setAttribute("ANTI_DUPLICATE_SUBMIT_TOKEN",token);
}else {
response.sendRedirect(request.getContextPath()+"/404.jsp?msg="+ URLEncoder.encode("请勿重复提交页面","utf-8"));
}
}
chain.doFilter(req, resp);
}
public void init(FilterConfig config) throws ServletException { }
}