一、前台验证

  1. 1.首先在from表单加一个隐藏域字段,设值为true。例如:
  2. <input type="hideen" name="tokenFlag" id="tokenFlag" value="true"/>
  3. 2.js中表单提交的验证方法中加判断,如下:
  4. var flag=$("#tokenFlag").val();
  5. if(flag=="true"){
  6. $("#tokenFlag").val('false');
  7. //业务代码(验证、跳转)
  8. }

二、session防止表单重新提交

具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
  在下列情况下,服务器程序将拒绝处理用户提交的表单请求:

  1. 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
  2. 当前用户的Session中不存在Token(令牌)
  3. 用户提交的表单数据中没有Token(令牌)

看具体的范例:

  1.创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面

  1. package xdp.gacl.session;
  2.  
  3. import java.io.IOException;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8.  
  9. public class FormServlet extends HttpServlet {
  10. private static final long serialVersionUID = -884689940866074733L;
  11.  
  12. public void doGet(HttpServletRequest request, HttpServletResponse response)
  13. throws ServletException, IOException {
  14.  
  15. String token = TokenProccessor.getInstance().makeToken();//创建令牌
  16. System.out.println("在FormServlet中生成的token:"+token);
  17. request.getSession().setAttribute("token", token); //在服务器使用session保存token(令牌)
  18. request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面
  19. }
  20.  
  21. public void doPost(HttpServletRequest request, HttpServletResponse response)
  22. throws ServletException, IOException {
  23. doGet(request, response);
  24. }
  25.  
  26. }

2.在form.jsp中使用隐藏域来存储Token(令牌)

  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
  2. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  3. <html>
  4. <head>
  5. <title>form表单</title>
  6. </head>
  7.  
  8. <body>
  9. <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" method="post">
  10. <%--使用隐藏域存储生成的token--%>
  11. <%--
  12. <input type="hidden" name="token" value="<%=session.getAttribute("token") %>">
  13. --%>
  14. <%--使用EL表达式取出存储在session中的token--%>
  15. <input type="hidden" name="token" value="${token}"/>
  16. 用户名:<input type="text" name="username">
  17. <input type="submit" value="提交">
  18. </form>
  19. </body>
  20. </html>

3.DoFormServlet处理表单提交

  1. package xdp.gacl.session;
  2.  
  3. import java.io.IOException;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServlet;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletResponse;
  8.  
  9. public class DoFormServlet extends HttpServlet {
  10.  
  11. public void doGet(HttpServletRequest request, HttpServletResponse response)
  12. throws ServletException, IOException {
  13.  
  14. boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
  15. if(b==true){
  16. System.out.println("请不要重复提交");
  17. return;
  18. }
  19. request.getSession().removeAttribute("token");//移除session中的token
  20. System.out.println("处理用户提交请求!!");
  21. }
  22.  
  23. /**
  24. * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
  25. * @param request
  26. * @return
  27. * true 用户重复提交了表单
  28. * false 用户没有重复提交表单
  29. */
  30. private boolean isRepeatSubmit(HttpServletRequest request) {
  31. String client_token = request.getParameter("token");
  32. //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
  33. if(client_token==null){
  34. return true;
  35. }
  36. //取出存储在Session中的token
  37. String server_token = (String) request.getSession().getAttribute("token");
  38. //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
  39. if(server_token==null){
  40. return true;
  41. }
  42. //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
  43. if(!client_token.equals(server_token)){
  44. return true;
  45. }
  46.  
  47. return false;
  48. }
  49.  
  50. public void doPost(HttpServletRequest request, HttpServletResponse response)
  51. throws ServletException, IOException {
  52. doGet(request, response);
  53. }
  54.  
  55. }

生成Token的工具类TokenProccessor

  1. package xdp.gacl.session;
  2.  
  3. import java.security.MessageDigest;
  4. import java.security.NoSuchAlgorithmException;
  5. import java.util.Random;
  6. import sun.misc.BASE64Encoder;
  7.  
  8. public class TokenProccessor {
  9.  
  10. /*
  11. *单例设计模式(保证类的对象在内存中只有一个)
  12. *1、把类的构造函数私有
  13. *2、自己创建一个类的对象
  14. *3、对外提供一个公共的方法,返回类的对象
  15. */
  16. private TokenProccessor(){}
  17.  
  18. private static final TokenProccessor instance = new TokenProccessor();
  19.  
  20. /**
  21. * 返回类的对象
  22. * @return
  23. */
  24. public static TokenProccessor getInstance(){
  25. return instance;
  26. }
  27.  
  28. /**
  29. * 生成Token
  30. * Token:Nv6RRuGEVvmGjB+jimI/gw==
  31. * @return
  32. */
  33. public String makeToken(){ //checkException
  34. // 7346734837483 834u938493493849384 43434384
  35. String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
  36. //数据指纹 128位长 16个字节 md5
  37. try {
  38. MessageDigest md = MessageDigest.getInstance("md5");
  39. byte md5[] = md.digest(token.getBytes());
  40. //base64编码--任意二进制编码明文字符 adfsdfsdfsf
  41. BASE64Encoder encoder = new BASE64Encoder();
  42. return encoder.encode(md5);
  43. } catch (NoSuchAlgorithmException e) {
  44. throw new RuntimeException(e);
  45. }
  46. }
  47. }

首先访问FormServlet,在FormServlet中生成Token之后再重定向到form.jsp页面,这次是在服务器端处理表单重复提交的,运行效果如下:

javaweb防止表单重新提交的更多相关文章

  1. JavaWeb防止表单重复提交(转载)

    转载自:http://blog.csdn.net/ye1992/article/details/42873219 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用 ...

  2. javaweb防止表单重复提交

    参考孤傲苍狼 https://www.cnblogs.com/xdp-gacl/p/3859416.html 场景一:在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交 场景二:表 ...

  3. (转)JavaWeb学习总结(十三)——使用Session防止表单重复提交

    如何防止表单重复提交 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复 ...

  4. JavaWeb 如何防止表单重复提交 - 使用Token,令牌

    JavaWeb 如何防止表单重复提交 - 使用Token,令牌 说到重复提交 ,应该想到两种场景:1. 在下单,或者支付 这种情况 那么不允许  刷新,不允许后退再点击提交(后退之后提交会失败,修改了 ...

  5. JavaWeb学习总结(十三)——使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  6. javaWeb学习总结(7)- 使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  7. JavaWeb学习 (十二)————使用Session防止表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

  8. JavaWeb温习之防止表单重复提交

    表单重复提交主要有以下三种情况: 1. 在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交 2. 表单提交后用户点击[刷新]按钮导致表单重复提交 3. 用户提交表单后,点击浏览器的 ...

  9. JavaWeb学习总结(十一):Session解决form表单重复提交

    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...

随机推荐

  1. 编译安装spark 1.5.x(Building Spark)

    原文连接:http://spark.apache.org/docs/1.5.0/building-spark.html · Building with build/mvn · Building a R ...

  2. webstorm 智能提示忽略大小写

    setting-Editor-General-Code Completion里的 Case sensitive completion: 可以设置只第一个字母敏感.完全敏感或者不敏感. 选择none.. ...

  3. Rabbitmq关于集群节点功能的读书笔记

    消息和队列可以指定是否持久化,如果指定持久化则会保存到硬盘上 ,不然只在内存里 普通集群模式下持久化的队列不能重建了 内存节点和磁盘节点的区别就是将元数据放在了内存还是硬盘,仅此而已,当在集群中声明队 ...

  4. SQL复制数据表 (select * into 与 insert into)

    select * into 目标表名 from 源表名 insert into 目标表名(fld1, fld2) select fld1, 5 from 源表名 以上两句都是将 源表 的数据插入到 目 ...

  5. 2012年蓝桥杯省赛A组c++第2题(暴力求解古堡算式)

    /* 古堡算式 福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式: ABCDE * ? = EDCBA 他对华生说:“ABCDE应该代表不同的数字,问号也代表某个数字!” 华生:“我猜也是!” 于是, ...

  6. python知识点杂记2

    1. 如果已经有一个list或者tuple,要调用一个可变参数怎么办?2. >>> nums = [1, 2, 3]3. >>> calc(*nums)4. 14* ...

  7. 【Mysql数据库访问利器】phpMyadmin

    缘由 我们程序员难免要和数据库打交道,经过这几年的锻炼,感觉手写SQL语句已经忘记的差不错了,促使我一定要这篇文章的原因是,有一次晚上我更新某个系统的数据库的表(由于目前公司比较严格,数据库都只能通过 ...

  8. disruptor的并行用法

    实现EventFactory,在newInstance方法中返回,ringBuffer缓冲区中的对象实例:代码如下: public class DTaskFactory implements Even ...

  9. TZOJ:最大连续子序列

    描述 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K.最大连续子 ...

  10. JavaScript学习笔记--语法

    代码风格: 每句结尾不用加分号: 单行注释用//,多行注释用/*...需要注释掉的代码....*/ 严格区分大小写 优雅的代码需要注意锁进 基础知识: Number:JavaScript不区分整数和浮 ...