精华内容
下载资源
问答
  • token机制详解 注:文内关于使用验证码图片的代码请参考我的另一篇博客 java Web项目中导入验证码图片功能步骤详解 ...解决方案:将转发改为重定向即可 2)由于网速或服务器的性能,导致处理请求满,用户重复点...

    token机制详解

    注:文内关于使用验证码图片的代码请参考我的另一篇博客
    java Web项目中导入验证码图片功能步骤详解

    重复提交的危害

    1)数据库可能会多次保存相同数据
    2)安全问题,如多次支付等
    3)服务器性能受损

    重复提交的几种情况

    1)成功提交后,直接刷新页面(每一次刷新就是重复上一次请求)

    解决方案:将转发改为重定向即可

    2)由于网速或服务器的性能,导致处理请求满,用户重复点击注册等提交表单按钮

    解决方案:将提交按钮点击后设为不可用。然后手动提交表单

    js页面代码:

    <script type="text/javascript">
    	window.onload=function(){
    		var btn=document.getElementById("subId");
    		btn.onclick=function(){
    			//将按钮设为不可点后 提交表单的动作被覆盖了
    			//所以我们需要手动提交表单
    			this.disabled=true;
    			//提交表单
    			var formEle=doucument.getElementById("form");
    			formEle.submit();
    		};
    	};
    </script>
    

    3)用户点击后退按钮,再次提交

    解决方案:由于http为无状态协议,浏览器无法分辨提交的请求是否上次已经提交过,所以我们在这里引入token的概念,通过token来判断是否重复提交
    每次提交表单,带上token令牌,服务器验证口令是否和我们在session域中取出的一致,一致则为合法请求,不一致则打回请求

    3.1)在session域中设置uuid

    <%
    	//产生一个唯一不重复的令牌当作token
    	String uuid= UUID.randomUUID().toString();
    	//放入session域中方便服务器验证
    	session.setAttribute("token", uuid);
    %>
    

    3.2)在表单提交时带上值为uuid的token参数

    <form action="login" id="form">
    	<label>用户名称:</label>
    	<input type="text" name="username" value="">
    	<br> <br>
    	<label>用户密码:</label>
    	<input type="password" name="pwd" value="">
    	<br> <br>
    	<label>验证码:</label>
    	<input type="text" style="width: 120px;"  name="code"/>
    	<img alt="" src="code.jpg" height="29px" width="70px" id="codeImg">
    	<input type="text" name="token" value=<%=uuid %>>
    	<input type="submit" value="登录" id="subId"> 
    </form>
    

    3.3)在servlet中接受用户提交时取出session域中存放的token和表单中带来的token

    String token=request.getParameter("token");
    HttpSession session = request.getSession();
    String tokenSession = (String) session.getAttribute("token");
    //从session中取出token后将域中token重新赋值
    session.setAttribute("token", UUID.randomUUID().toString());
    	if(token.equals(tokenSession)) {
    		//token相同 合法请求
    	}else {
    			//token不相同,打回请求
    		}
    

    3.3)关于为什么这样编写后可以防止用户返回后重新提交及为何要重新设置session域中token值详解
    在这里插入图片描述

    用户第一次点击登录,session域和表单提交带上的token是相同的,servlet接收到请求后会对两者取出的token进行比较,成功则继续请求,反之打回请求。
    不管成功与否,服务器都会将session域中的token重新设置,而当用户返回后重新提交,表单中token的值是在缓存中取出的,而session域中的token已经是在servlet中被重新赋值了的,两个自然不同,请求被认定为非法请求,直接打回

    仅在学习过程中记录所学内容,如有何处不足还请大佬们指出,欢迎同行一起交流。联系我微信chenhan-wu,记得备注csdn

    在这里插入图片描述

    展开全文
  • 解决表单重复提交解决方案——在服务端对Token进行验证 1、在idea中建立一个springboot项目 2、在templates目录下建立一个index.html文件 <!DOCTYPE html> <... xmlns:contex...

    解决表单重复提交的解决方案——在服务端对Token进行验证

    1、在idea中建立一个springboot项目

    2、在templates目录下建立一个index.html文件

    <!DOCTYPE html>
    <html lang="en" xmlns:mvc="http://www.springframework.org/schema/mvc"
          xmlns:context="http://www.springframework.org/schema/context">
    <head>
        <mvc:annotation-driven enable-matrix-variables="true"/>
        <context:component-scan base-package="com.example.demo"/>
        <mvc:default-servlet-handler/>
        <meta charset="utf-8" />
        <title>首页</title>
    
    </head>
    <body>
    <p>
        <a href="/h2">链接</a>   //点击链接,来到表单提交页面
    </p>
    </body>
    </html>
    

    3、在templates目录下建立index3.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script type="text/javascript" src="/b/js/jquery-3.4.1.min.js"></script>
        <script>
            function f2() {
                $.ajax({
                    url:"/get_token",    //向服务器端发送的请求地址
                    success:function (data) {
                        console.log(data);
                       $("#h").val(data)    //把返回的token放入input中,随表单提交给后端
                    }
                })
            }
        </script>
    </head>
    <body>
     <form action="/h3" id="dd" method="post">
         用户名:<input type="text" id="u" name="user_name">
         密码:<input type="text" id="p" name="psd" onblur="f2()">    //当鼠标离开密码输入框时,触发f()函数,向后端发送一个ajax请求
         <input type="submit" value="提交" >
         <input type="hidden" id="h" name="token">   //通过ajax请求,把服务端生成的token放入该input中
     </form>
    </body>
    </html>
    

    4、建立一个Controller

    package com.example.demo.controller;
    
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpSession;
    import java.util.UUID;
    
    @Controller
    public class Token_controller {
    
    
        @ResponseBody
        @RequestMapping("/get_token")  //利用ajax请求,给前端返回一个token
        public String get1(HttpServletRequest httpServletRequest) {
            UUID uuid = UUID.randomUUID();  //利用UUID获得一个token,返回给前端的表单中
            String str = uuid.toString();
            HttpSession session = httpServletRequest.getSession();
            session.setAttribute("token", str);
            return str;
        }
    
    
        @RequestMapping("/h2")
        public String get2() {
    
            return "index3";
        }
    
    
        @RequestMapping("/h3")
        public String get3(String token, HttpServletRequest httpServletRequest) throws InterruptedException {
    
            Thread.sleep(3000);  //让线程等待3秒,模拟网络拥挤的情况
            HttpSession session = httpServletRequest.getSession();
            String tokens = (String) session.getAttribute("token");
            if (tokens == null || tokens.equals("") || (!(tokens.equals(token)))) //判断从session中是否有token,若无则表单重复提交,若session
            {                                                             //中的token值与前端表单中传过来的值不相同,也提示表单重复提交
                System.out.println("提交失败!");
    
            } else {                                                      //表单提交成功
                System.out.println("提交成功!");
                session.removeAttribute("token");
                return "index";
            }
    
            return "index";    //返回首页
    
        }
    
    
    }
    
    

    5、运行项目

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    点击多次提交按钮,只有一个请求被接收,从根本上解决了表单重复提交的问题!

    6、总结

    1、在导入jQuery时要注意路径问题,若出现无法加载jQuery的问题,首先检查jQuery所在的静态资源路径是否被拦截,在springboot2.0以后,会默认拦截静态资源,需要添加一个WebMvcConfigurer来添加静态资源的目录。如果不是这个问题,再检查jQuery的请求路径是否正确,一般都是出现这个问题。
    2、在后端对tokens进行判断是应该用(tokens == null || tokens.equals("")),不然会报空指针异常。
    3、在服务器端解决是根本的方法,常用的其他几种方法,例如在前端进行判断有他的局限性,若用户点击后退,表单还是会进行再次提交。

    展开全文
  • 转自...本文正是通过使用session以及在session中加入token,来验证同一个操作人员是否进行了并发重复的请求,在后一个请求到来时,使用session中的token

    转自http://www.iflym.com/index.php/code/avoid-conrrent-duplicate-submit-by-use-session-synchronized-and-token.html 

    本文正是通过使用session以及在session中加入token,来验证同一个操作人员是否进行了并发重复的请求,在后一个请求到来时,使用session中的token验证请求中的token是否一致,当不一致时,被认为是重复提交,将不准许通过。
        整个流程可以由如下流程来表述:

    1. 客户端申请token
    2. 服务器端生成token,并存放在session中,同时将token发送到客户端
    3. 客户端存储token,在请求提交时,同时发送token信息
    4. 服务器端统一拦截同一个用户的所有请求,验证当前请求是否需要被验证(不是所有请求都验证重复提交)
    5. 验证session中token是否和用户请求中的token一致,如果一致则放行
    6. session清除会话中的token,为下一次的token生成作准备
    7. 并发重复请求到来,验证token和请求token不一致,请求被拒绝

        由以上的流程,我们整个实现需要以下几个东西

    1. token生成器,负责生成token
    2. 客户token请求处理action,负责处理客户请求,并返回token信息
    3. token拦截器,用于拦截指定的请求是否需要验证token
    4. token请求拦截标识,用于标识哪些请求是需要被拦截的
    5. 客户端token请求处理方法,用于请求token,并存放于特定操作中,并在提交时发送到请求中
    展开全文
  • 什么是token token其实就是一个令牌,具有随机性,类似于sessionId。 在对接一些第三方平台的时候,为了能够保证数据安全性,通常会使用一些令牌进行交互。 from.jsp: <%@ page language="java" contentType="text/...

    什么是token
    token其实就是一个令牌,具有随机性,类似于sessionId。
    在对接一些第三方平台的时候,为了能够保证数据安全性,通常会使用一些令牌进行交互。
    from.jsp:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
      <head>
        <title>Form表单</title>
      </head>
      
      <body>
          <form action="${pageContext.request.contextPath}/DoFormServlet" method="post">
            用户名:<input type="text" name="userName">
            <input type="submit" value="提交" id="submit">
        </form>
      </body>
    </html>
    

    处理类:

    WebServlet("/DoFormServlet")
    public class DoFormServlet extends HttpServlet {
    
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.setCharacterEncoding("UTF-8");
    		String userName = req.getParameter("userName");
    		try {
    			Thread.sleep(300);
    		} catch (Exception e) {
    			// TODO: handle exception
    		}
    		System.out.println("往数据库插入数据...."+userName);
    		resp.getWriter().write("success");
    	}
    }
    

    造成表单重复提交的原因:
    场景一: 在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交。
    场景二:按钮导致表单重复提交
    场景三:按钮回退到表单页面后进行再次提交
    场景四:用户提交表单后,点击浏览器的【后退】按钮回退到表单页面后进行再次提交
    解决方案
    使用javascript 解决
     既然存在上述所说的表单重复提交问题,那么我们就要想办法解决,比较常用的方法是采用JavaScript来防止表单重复提交,具体做法如下:
    修改form.jsp页面,添加如下的JavaScript代码来防止表单重复提交

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Form表单</title>
    <script type="text/javascript">
    	var isFlag = false; //表单是否已经提交标识,默认为false
    
    	function submitFlag() {
    
    		if (isFlag == false) {
    			isFlag = true;
    			return true;
    		} else {
    			return false;
    		}
    
    	}
    </script>
    </head>
    
    <body>
    	<form action="${pageContext.request.contextPath}/DoFormServlet"
    		method="post" onsubmit="return submitFlag()">
    		用户名:<input type="text" name="userName"> <input type="submit"
    			value="提交" id="submit">
    	</form>
    </body>
    </html>
    

    除了用这种方式之外,经常见的另一种方式就是表单提交之后,将提交按钮设置为不可用,让用户没有机会点击第二次提交按钮,代码如下:

    function dosubmit(){
        //获取表单提交按钮
        var btnSubmit = document.getElementById("submit");
        //将表单提交按钮设置为不可用,这样就可以避免用户再次点击提交按钮
        btnSubmit.disabled= "disabled";
        //返回true让表单可以正常提交
        return true;
    }
    

    ** 使用后端提交解决**
     对于【场景二】和【场景三】导致表单重复提交的问题,既然客户端无法解决,那么就在服务器端解决,在服务器端解决就需要用到session了。
      具体的做法:在服务器端生成一个唯一的随机标识号,专业术语称为Token(令牌),同时在当前用户的Session域中保存这个Token。然后将Token发送到客户端的Form表单中,在Form表单中使用隐藏域来存储这个Token,表单提交的时候连同这个Token一起提交到服务器端,然后在服务器端判断客户端提交上来的Token与服务器端生成的Token是否一致,如果不一致,那就是重复提交了,此时服务器端就可以不处理重复提交的表单。如果相同则处理表单提交,处理完后清除当前用户的Session域中存储的标识号。
    在下列情况下,服务器程序将拒绝处理用户提交的表单请求:
    1.存储Session域中的Token(令牌)与表单提交的Token(令牌)不同。
    2.当前用户的Session中不存在Token(令牌)。
    3.用户提交的表单数据中没有Token(令牌)。
    转发处理类:

    @WebServlet("/ForwardServlet")
    public class ForwardServlet extends HttpServlet {
    	@Override
    	protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.getSession().setAttribute("sesionToken", TokenUtils.getToken());
    		req.getRequestDispatcher("form.jsp").forward(req, resp);
    	}
    }
    

    转发页面:

    <%@ page language="java" contentType="text/html; charset=UTF-8"
    	pageEncoding="UTF-8"%>
    <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
    <html>
    <head>
    <title>Form表单</title>
    
    </head>
    
    <body>
    	<form action="${pageContext.request.contextPath}/DoFormServlet"
    		method="post" onsubmit="return dosubmit()">
    		<input type="hidden" name="token" value="${sesionToken}"> 用户名:<input type="text"
    			name="userName"> <input type="submit" value="提交" id="submit">
    	</form>
    </body>
    </html>
    

    处理类:

    @WebServlet("/DoFormServlet")
    public class DoFormServlet extends HttpServlet {
    	@Override
    	protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
    		req.setCharacterEncoding("UTF-8");
    		boolean flag = isFlag(req);
    		if (!flag) {
    			resp.getWriter().write("已经提交...");
    			System.out.println("数据已经提交了..");
    			return;
    		}
    		String userName = req.getParameter("userName");
    		try {
    			Thread.sleep(300);
    		} catch (Exception e) {
    			// TODO: handle exception
    		}
    		System.out.println("往数据库插入数据...." + userName);
    		resp.getWriter().write("success");
    	}
    
    	public boolean isFlag(HttpServletRequest request) {
    		HttpSession session = request.getSession();
    		String sesionToken = (String) session.getAttribute("sesionToken");
    		String token = request.getParameter("token");
    		if (!(token.equals(sesionToken))) {
    			return false;
    		}
    		session.removeAttribute("sesionToken");
    		return true;
    	}
    }
    
    展开全文
  • 本文介绍如何使用token来防止前端重复提交的问题。 目录 1.思路 2.拦截器源码实现 3.注解源码 4.拦截器的配置 5.使用指南 6.结语 思路 1.添加拦截器,拦截需要防重复提交的请求 2.通过注解@Token来添加token/...
  • 表单重复提交解决方案(防止Http重复提交 场景模拟 创建一个from.jsp页面 &amp;lt;%@ page language=&quot;java&quot; contentType=&quot;text/html; charset=UTF-8&quot; pageEncoding=&...
  • 引发表单重复提交的一些场景: 网络延时  在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在...
  • 前言以前在很多p2p网站中,都有新手领取...我们先拦截url请求,Shift+R,填入压力测试的次数,然后释放,就会造成很多次的url访问请求,这样的结果很容易造成表单重复提交。那么我们的今天主题就是如何使用Session和T
  • springboot解决form表单重复提交方案

    千次阅读 2019-05-17 11:15:57
     在实际业务系统应用过程中,都会存在一个表单数据重复提交的问题。针对这个问题网上也存在N多种解决方案。  为节省选择时间,因此在这N多种方案中,我整理了自认为从根本上解决重复提交的问题的一个最优方案。 ...
  • 阅读目录前言form重复提交场景解决方案一:前端利用JavaScript防止表单重复提交二:利用Session防止表单重复提交参考 前言 如果网速比较慢的情况下,用户点击的提交发现半天没有反映,于是又重新点击了几次提交按钮...
  • 表单重复提交问题解决方案

    千次阅读 2018-09-18 17:10:25
    2.网速较慢的情况,我们让表单中的提交按钮只能提交一次,然后就不能再次点击了 &lt;form action="FormServlet" method="post"&gt; &lt;input type="text" name="...
  • 表单重复提交解决方案(防止Http重复提交)(重点) -使用后端提交解决 使用Fileter防止XSS(js脚本注入)攻击及案例(重点) Web安全方面的几种攻击方式 一、http长连接与短连接 在HTTP/1.0中,默认使用的...
  • 保证接口幂等性,表单重复提交 前台解决方案:提交后按钮禁用、置灰、页面出现遮罩后台解决方案: 使用token,每个token只能使用一次1.在调用接口之前生成对应的Token,存放至redis 2.在调用接口时,将生成的...
  • java web 防止表单重复提交解决方案

    千次阅读 2015-12-05 10:48:25
    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交。 一、表单重复...
  • 最近在做项目遇到表单重复提交的问题,前后端完全分离的项目,采用的的是基于Token注解+拦截器的方式解决的,大概的思路是: 1、前端先请求后台一个方法,后台生成token并保存在session中,然后再将token返回给前端...
  • 解决表单重复提交的问题

    千次阅读 2017-07-20 20:16:34
    现象描述最近在开发的时候,遇见这样的问题,当我们在网络状况不太好的情况、或者一个业务的后台业务逻辑执行时间较长的时候,用户可能会点击多次提交或刷新多次页面,导致表单数据被提交了多次,导致了可能出现...
  • 表单重复提交是在多用户Web应用中最常见、带来很多麻烦的一个问题。有很多的应用场景都会遇到重复提交问题,比如: 点击提交按钮两次。 点击刷新按钮。 使用浏览器后退按钮重复之前的操作,导致重复提交表单。 使用...
  • IP协议主要解决网络路由和寻址问题,TCP协议主要解决如何在IP层之上可靠的传递数据包,使在网络上的另一端收到发端发出的所有包,并且顺序与发出顺序一致。TCP有可靠,面向连接的特点。 如何理解HTT...
  • 一、概念 幂等性, 通俗的说就是一个接口, 多次发起同一个请求, 必须保证操作只能执行一次 比如: 订单接口, 不能多次创建订单 ... token机制 -- 防止页面重复提交 悲观锁 -- 获取数据的时候加锁(锁表或锁行)...
  • 怎样防止表单重复提交,通过搜索引擎能搜到很多结果,但很零散,系统性不强,正好前几天做了这个功能,决定记录下来。 根据数据流向的过程,分别在三个“点”控制表单的重复提交,如下:第一,用户触发submit时,...
  • 重复提交解决方案

    2021-03-01 17:11:53
    重复提交解决方案
  • 解决分布式表单重复提交问题

    千次阅读 2018-07-11 20:23:13
    然后赶紧学习一下怎么解决表单重复提交的办法,最后发现下面的这篇博客。博客地址:https://blog.csdn.net/zwb19940216/article/details/78151899一、为什么会出现重复提交?主要是由于网络的延迟问题以及页面刷新的...
  • 参考网上的一些资料:通过前端 + 后端 一起来阻止表单重复提交 这边整理出2种 ,前端大家参考一下,我主要是用后端,跑一个demo实际的演示一下 源码我放到github上,欢迎大家下载:...
  • 解决表单重复提交的简单方法

    千次阅读 2018-07-26 16:38:47
    在平时开发中,如果网速比较慢的情况下,用户提交表单后,发现服务器半天都没有响应,那么用户可能会以为是自己没有提交表单,就会再点击提交按钮重复提交表单,我们在开发中必须防止表单重复提交。 一、表单重复...
  • javaweb防止表单重复提交的几种解决方案 在javaweb方向做开发的小伙伴们,肯定都会遇到表单重复提交的问题。 javaweb防止表单重复提交的几种解决方案 这种问题出现的原因或者说应用场景大致如下: 网络延迟,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,962
精华内容 2,384
关键字:

token表单重复提交解决方案