Java中的表单重复提交问题

  • 问题:使用forward转发请求后,再次刷新当前页面,会进行重复提交;
  • 例子:使用LoginServlet进行登录,成功后跳转到login页面,刷新当前页面,再次直接进行了登录;如果这是支付、买票等页面,重复提交将导致严重后果。因此要解决重复提交的问题。
  • 为了能够解决重复提交问题,关键在于:能够标志一次提交,从而识别出该提交已经处理。下面是主要处理过程:
/*login.jsp页面,主要作用是用一个不可见的input来存令牌的值*/
<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>
//LoginServlet用来处理登录请求
@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");
        //如果令牌不存在,就生成一个新的令牌放到session中去
        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 {  }

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值