javaweb防止表单重新提交
一、前台验证
- 1.首先在from表单加一个隐藏域字段,设值为true。例如:
- <input type="hideen" name="tokenFlag" id="tokenFlag" value="true"/>
- 2.在js中表单提交的验证方法中加判断,如下:
- var flag=$("#tokenFlag").val();
- if(flag=="true"){
- $("#tokenFlag").val('false');
- //业务代码(验证、跳转)
- }
二、session防止表单重新提交
具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
在下列情况下,服务器程序将拒绝处理用户提交的表单请求:
- 存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
- 当前用户的Session中不存在Token(令牌)。
- 用户提交的表单数据中没有Token(令牌)。
看具体的范例:
1.创建FormServlet,用于生成Token(令牌)和跳转到form.jsp页面
- package xdp.gacl.session;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class FormServlet extends HttpServlet {
- private static final long serialVersionUID = -884689940866074733L;
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- String token = TokenProccessor.getInstance().makeToken();//创建令牌
- System.out.println("在FormServlet中生成的token:"+token);
- request.getSession().setAttribute("token", token); //在服务器使用session保存token(令牌)
- request.getRequestDispatcher("/form.jsp").forward(request, response);//跳转到form.jsp页面
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
2.在form.jsp中使用隐藏域来存储Token(令牌)
- <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
- <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
- <html>
- <head>
- <title>form表单</title>
- </head>
- <body>
- <form action="${pageContext.request.contextPath}/servlet/DoFormServlet" method="post">
- <%--使用隐藏域存储生成的token--%>
- <%--
- <input type="hidden" name="token" value="<%=session.getAttribute("token") %>">
- --%>
- <%--使用EL表达式取出存储在session中的token--%>
- <input type="hidden" name="token" value="${token}"/>
- 用户名:<input type="text" name="username">
- <input type="submit" value="提交">
- </form>
- </body>
- </html>
3.DoFormServlet处理表单提交
- package xdp.gacl.session;
- import java.io.IOException;
- import javax.servlet.ServletException;
- import javax.servlet.http.HttpServlet;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletResponse;
- public class DoFormServlet extends HttpServlet {
- public void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- boolean b = isRepeatSubmit(request);//判断用户是否是重复提交
- if(b==true){
- System.out.println("请不要重复提交");
- return;
- }
- request.getSession().removeAttribute("token");//移除session中的token
- System.out.println("处理用户提交请求!!");
- }
- /**
- * 判断客户端提交上来的令牌和服务器端生成的令牌是否一致
- * @param request
- * @return
- * true 用户重复提交了表单
- * false 用户没有重复提交表单
- */
- private boolean isRepeatSubmit(HttpServletRequest request) {
- String client_token = request.getParameter("token");
- //1、如果用户提交的表单数据中没有token,则用户是重复提交了表单
- if(client_token==null){
- return true;
- }
- //取出存储在Session中的token
- String server_token = (String) request.getSession().getAttribute("token");
- //2、如果当前用户的Session中不存在Token(令牌),则用户是重复提交了表单
- if(server_token==null){
- return true;
- }
- //3、存储在Session中的Token(令牌)与表单提交的Token(令牌)不同,则用户是重复提交了表单
- if(!client_token.equals(server_token)){
- return true;
- }
- return false;
- }
- public void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- doGet(request, response);
- }
- }
生成Token的工具类TokenProccessor
- package xdp.gacl.session;
- import java.security.MessageDigest;
- import java.security.NoSuchAlgorithmException;
- import java.util.Random;
- import sun.misc.BASE64Encoder;
- public class TokenProccessor {
- /*
- *单例设计模式(保证类的对象在内存中只有一个)
- *1、把类的构造函数私有
- *2、自己创建一个类的对象
- *3、对外提供一个公共的方法,返回类的对象
- */
- private TokenProccessor(){}
- private static final TokenProccessor instance = new TokenProccessor();
- /**
- * 返回类的对象
- * @return
- */
- public static TokenProccessor getInstance(){
- return instance;
- }
- /**
- * 生成Token
- * Token:Nv6RRuGEVvmGjB+jimI/gw==
- * @return
- */
- public String makeToken(){ //checkException
- // 7346734837483 834u938493493849384 43434384
- String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";
- //数据指纹 128位长 16个字节 md5
- try {
- MessageDigest md = MessageDigest.getInstance("md5");
- byte md5[] = md.digest(token.getBytes());
- //base64编码--任意二进制编码明文字符 adfsdfsdfsf
- BASE64Encoder encoder = new BASE64Encoder();
- return encoder.encode(md5);
- } catch (NoSuchAlgorithmException e) {
- throw new RuntimeException(e);
- }
- }
- }
首先访问FormServlet,在FormServlet中生成Token之后再重定向到form.jsp页面,这次是在服务器端处理表单重复提交的,运行效果如下:
javaweb防止表单重新提交的更多相关文章
- JavaWeb防止表单重复提交(转载)
转载自:http://blog.csdn.net/ye1992/article/details/42873219 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用 ...
- javaweb防止表单重复提交
参考孤傲苍狼 https://www.cnblogs.com/xdp-gacl/p/3859416.html 场景一:在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交 场景二:表 ...
- (转)JavaWeb学习总结(十三)——使用Session防止表单重复提交
如何防止表单重复提交 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复 ...
- JavaWeb 如何防止表单重复提交 - 使用Token,令牌
JavaWeb 如何防止表单重复提交 - 使用Token,令牌 说到重复提交 ,应该想到两种场景:1. 在下单,或者支付 这种情况 那么不允许 刷新,不允许后退再点击提交(后退之后提交会失败,修改了 ...
- JavaWeb学习总结(十三)——使用Session防止表单重复提交
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...
- javaWeb学习总结(7)- 使用Session防止表单重复提交
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...
- JavaWeb学习 (十二)————使用Session防止表单重复提交
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...
- JavaWeb温习之防止表单重复提交
表单重复提交主要有以下三种情况: 1. 在网络延迟的情况下让用户有时间点击多次submit按钮导致表单重复提交 2. 表单提交后用户点击[刷新]按钮导致表单重复提交 3. 用户提交表单后,点击浏览器的 ...
- JavaWeb学习总结(十一):Session解决form表单重复提交
在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交. 一.表单重复提 ...
随机推荐
- 编译安装spark 1.5.x(Building Spark)
原文连接:http://spark.apache.org/docs/1.5.0/building-spark.html · Building with build/mvn · Building a R ...
- webstorm 智能提示忽略大小写
setting-Editor-General-Code Completion里的 Case sensitive completion: 可以设置只第一个字母敏感.完全敏感或者不敏感. 选择none.. ...
- Rabbitmq关于集群节点功能的读书笔记
消息和队列可以指定是否持久化,如果指定持久化则会保存到硬盘上 ,不然只在内存里 普通集群模式下持久化的队列不能重建了 内存节点和磁盘节点的区别就是将元数据放在了内存还是硬盘,仅此而已,当在集群中声明队 ...
- SQL复制数据表 (select * into 与 insert into)
select * into 目标表名 from 源表名 insert into 目标表名(fld1, fld2) select fld1, 5 from 源表名 以上两句都是将 源表 的数据插入到 目 ...
- 2012年蓝桥杯省赛A组c++第2题(暴力求解古堡算式)
/* 古堡算式 福尔摩斯到某古堡探险,看到门上写着一个奇怪的算式: ABCDE * ? = EDCBA 他对华生说:“ABCDE应该代表不同的数字,问号也代表某个数字!” 华生:“我猜也是!” 于是, ...
- python知识点杂记2
1. 如果已经有一个list或者tuple,要调用一个可变参数怎么办?2. >>> nums = [1, 2, 3]3. >>> calc(*nums)4. 14* ...
- 【Mysql数据库访问利器】phpMyadmin
缘由 我们程序员难免要和数据库打交道,经过这几年的锻炼,感觉手写SQL语句已经忘记的差不错了,促使我一定要这篇文章的原因是,有一次晚上我更新某个系统的数据库的表(由于目前公司比较严格,数据库都只能通过 ...
- disruptor的并行用法
实现EventFactory,在newInstance方法中返回,ringBuffer缓冲区中的对象实例:代码如下: public class DTaskFactory implements Even ...
- TZOJ:最大连续子序列
描述 给定K个整数的序列{ N1, N2, ..., NK },其任意连续子序列可表示为{ Ni, Ni+1, ..., Nj },其中 1 <= i <= j <= K.最大连续子 ...
- JavaScript学习笔记--语法
代码风格: 每句结尾不用加分号: 单行注释用//,多行注释用/*...需要注释掉的代码....*/ 严格区分大小写 优雅的代码需要注意锁进 基础知识: Number:JavaScript不区分整数和浮 ...