表单的重复提交
1)重复提交的情况
1>在表单提交到一个Servlet,而Servlet又通过请求转发的方式响应了一个JSP(HTML)页面,此时地址栏还保留着Servlet的那个路径,在响应页面点击“刷新”。
2>在响应页面没有到达时重复点击“提交按钮”
3>点击“返回”,再点击“提交”
2)不是重复提交的情况
1>点击“返回”,“刷新”原表单页面,再“提交”
3)如何避免表单的重复提交
1>在表单中做一个标记,提交到Servlet时,检查标记是否存在且是否和预定义的标记一致,若一致,则受理请求,并销毁标记,若不一致或没有标记,则直接响应提示信息:“重复提交”
(1)仅提供一个隐藏域:行不通:没有办法清除固定的请求参数。
(2)把标记放在request中,行不通,因为表单页面刷新后,request已经被销毁,再提交表单是一个新的request。
(3)把标记放在session中,可以!
>在原表单页面,生成一个随机值token
>在原表单页面,把token值放入session属性中
>在原表单页面,把token值放入隐藏域中。
——提交表单
>在目标的servlet中:获取session和隐藏域中的token值
>比较两个值是否一致:若一致,受理请求,且把session域中的token属性清除
>若不一致,则直接响应提示页面:"重复提交"
原理:在原表单页面,创建一个session属性,和隐藏域,两个值开始时是一个相同的随机值,当进入servlet中比较两个值是否相同,相同删除session属性。
login.jsp
单击提交表单
点击返回,点击提交表单。
刷新原表单页面,连续点击提交
源码:
login.jsp
Created by IntelliJ IDEA.
User: dell
Date: 2019/7/11
Time: 16:05
To change this template use File | Settings | File Templates.
--%>
TitleString tokenValue = new Date().getTime() + "";
session.setAttribute("token",tokenValue);
%>
name:
tokenservlet
package com.demo.servlet;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class TokenServlet extends HttpServlet {
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
HttpSession session = req.getSession();
Object token = session.getAttribute("token");
String tokenValue = req.getParameter("token");
System.out.println(token);
System.out.println(tokenValue);
if (token!=null&&token.equals(tokenValue)){
session.removeAttribute("token");
}else{
resp.sendRedirect(req.getContextPath()+"/stoken/error.jsp");
return;
}
String name = req.getParameter("name");
System.out.println("name: " +name);
resp.sendRedirect(req.getContextPath()+"/stoken/success.jsp");
}
}