避免表单重复提交与等待页面

一.为什么会出现表单重复提交

   1.当用户在表单中填写完信息,点击提交按钮后,肯能会因为没有看到成功信息而在此点击提交按钮,从而导致在服务器端收到两条同样的信息,如果这个信息要保存到数据库中的,那么就会出现两条重复的数据,或者可能出现数据库操作异常。

2.当用户填写表单信息完成后,点击表单提交,即使响应及时,也有可能会出现表单重复提交的情况。一般服务器端的程序在处理完用户提交的信息后,调用的是Request.Dispatcher.forward()方法将用户的请求导向成功页面,用户看到成功信息后,点击刷新,此时浏览器将再次提交用户先前输入的数据,刚才说了这是因为调用Request.Dispatcher.forward()方法返回成功页面的,浏览器锁保留的url是先前表单提交的url,如果采用的是HttpServletResponse.sendRedirect()方法将客户端重定向到成功页面,就不会出现重复提交的问题了。

二.避免表单重复提交的原理

避免表单重复提交有两种方案,一种是在JavaScript脚本上,第二种是在服务器端来阻止表单重复提交,我们主要那么这里我们主要针对的是服务器端来处理表单的重复提交.

1.用访问包含表单的页面,服务器端在这次会话中,创建一个session对象,并产生一个令牌值,将这个令牌值作为隐藏输入域的值,随表单一起发送到客户端,同事将令牌值保存到session中。

2.用户提交页面,服务器端首先判断请求参数中的令牌值和Session中保存到额令牌值是否相等,如果相等,则清楚Session中的令牌值,然后执行数据吃了操作,如果不相等,则提示用户已经提交过表单了,同时产生一个新的令牌值,保存到Session中,当用户重新访问提交数据页面时,将新产生的令牌值作为隐藏输入域的值。

三.使用Struts2来实现防止表单重复提交

Struts2使拦截器来检查表单是否重复提交,他也是采用同步令牌的方式来实现对表单重复提交的判断。

第一步:

首先要在表中使用<s:token>标签,并指定一二令牌的名字,<s:token>标签用来创建一个新的令牌值,并用你所指定的令牌名把令牌值保存到Session中,这个令牌值是随机产生的经过加密的字符序列。

从上图中可以看出,<s:token>标签会在表单中生成两个隐藏字段。第一个隐藏字段的名字是固定的,struts.token.name.第二个隐藏字段的名字是<s:token>标签name属性的值,他的值就是随机产生的经过加密的令牌值。服务器端的拦截器首先根据struts.token.name请求参数找到保存了令牌值的请求参数名user.token,然后在获取user.token请求参数,得到令牌的值。

第二步:

需要在Action配置引用TokenInterceptor或者TokenSessionStoreInterceptor拦截器,这两个拦截器已经在struts-defatul.xml中定义,但没有包含在defaultStatck拦截器中。

我们这里先使用TokenInterceptor拦截器,当表单提交时,TokenInterceptor拦截器获取请求,获取标准的struts.token.name请求参数,得到保存了令牌值的请求参数名,然后再根据这个请求的参数获取令牌值,接着TokenInterceptor根据刚才得到的令牌名,从session中取出<s:token>标签先前保存到session中的令牌值,对两个令牌值进行比较。如果session中的令牌值等于请求参数中的令牌值,那么删除session中的令牌值,并调用handleValidToken()方法,该方法直接调用,他首先调用Action的方法对请求进行处理;如果两个值不相等,那么handelInvalidToken()方法被调用,它首先添加一个Action级别的错误消息到这个Action(Action需要实现ValidationAware,ActionSupport基类实现了该接口),然后直接返回INVALID_TOKEN_CODE结果码,从而跳过Action的执行。INVALID_TOKEN_CODE是一个在TokenInterceptor中定义的静态常量,值为invalid.token

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
    "http://struts.apache.org/dtds/struts-2.3.dtd">
<struts>

    <!-- 配置文件中只要添加以下配置,那么以后修改配置文件不用重启 tomcat -->
    <constant name="struts.devMode" value="true" /><!--name:常量的名称 value:常量的值 -->

    <!--处理中文乱码问题的解决 -->
    <!--国际化信息内码 -->
    <constant name="struts.i18n.encodeing" value="UTF-8" />

    <package name="default" namespace="/" extends="struts-default">
       <action name="token" class="cn.action.RegistAction" >
             <!-- 配置Token拦截器 -->
            <interceptor-ref name="defaultStack"></interceptor-ref>
            <interceptor-ref name="token"></interceptor-ref>
            <!-- 如果重复提交,则跳转到error.jsp -->
            <result name="invalid.token">/error.jsp</result>
            <result name="success">/success.jsp</result>

       </action>
    </package>
</struts>
    

action:

package cn.action;

import com.opensymphony.xwork2.ActionSupport;

public class RegistAction extends ActionSupport{

    private String name;
    private String pwd;
    @Override
    public String execute() throws Exception {
        for (int i = 0; i < 5000000; i++) {
            System.out.println("====");
        }
        return SUCCESS;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public String getPwd() {
        return pwd;
    }
    public void setPwd(String pwd) {
        this.pwd = pwd;
    }

}

注册页面:

<body>      <s:actionerror/>
      <s:form action="token">
        <s:token name="user.token"></s:token>
        <s:textfield label="用户名" name="name"></s:textfield>
        <s:password label="密码" name="pwd"></s:password>
        <s:submit value="提交"></s:submit>
      </s:form>
  </body>

如果用户连续提交两次,便会走造成表单重复提交,会跳到该页面显示错误信息。也可以通过配置来该错误提示信息。

时间: 2024-12-15 03:59:58

避免表单重复提交与等待页面的相关文章

表单重复提交问题

一.常见的重复提交问题  a>点击提交按钮两次.  b>点击刷新按钮.  c>使用浏览器后退按钮重复之前的操作,导致重复提交表单.  d>使用浏览器历史记录重复提交表单.  e>浏览器重复的HTTP请求. 二.防止表单重复提交原理 提交表单的时候提交一份随机的字符串或随机数字等等,再把这个随机的数据存到request里面,然后把表单数据提交,在后台验证的时候判断提交的这两份额外的数据是否一致,如果一致,则把其中一份删除掉,这么做的目的是防止再次提交,继续进行操作,如果不一致,

防止表单重复提交

客户端防止表单重复提交: 不足之处:用户单击”刷新”,或单击”后退”再次提交表单,将导致表单重复提交 <script type="text/javascript"> //方式一 var iscommitted = false; function dosubmit(){ if(!iscommitted){ iscommitted = true; return true; }else{ return false; } } //方式二 function dosubmit(){ d

[原创]java WEB学习笔记34:Session 案例 之 解决表单重复提交

本博客为原创:综合 尚硅谷(http://www.atguigu.com)的系统教程(深表感谢)和 网络上的现有资源(博客,文档,图书等),资源的出处我会标明 本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 ---------------------------------

php 解决和避免form表单重复提交的方法

在提交表单的时候,可能遇到网速等导致页面突然加载变慢,用户重复地点击提交按钮,将在数据库产生多条数据,导致不可控情况. 比如下面的情况就会导致表单重复提交: 点击提交按钮两次. 点击刷新按钮. 使用浏览器后退按钮重复之前的操作,导致重复提交表单. 使用浏览器历史记录重复提交表单. 浏览器重复的HTTP请求. 网页被恶意刷新. 下面是几种解决的方法: 一:利用js设置按钮点击后变成灰色 $(document).ready(function(){ $(input:submit).click(){ s

[PHP]防止表单重复提交的几种方法

--------------------------------------------------------------------------------------------------- 1. 使用JS让按钮在点击一次后禁用(disable).=> 防止多次点击发生,实现方式较简单. 缺点:若客户端禁止JavaScript脚本,则失效. 2. 在提交成功后执行页面重定向(redirect).=> 转到提交成功信息页面. 特点:避免F5重复提交,消除浏览器前进和后退按导致的同样问题.

表单重复提交--笔记

同一个表单中的内容多次提交到服务器中. 第一种情况:    提交完表单以后,不做其他操作,直接刷新页面,表单会提交多次.    - 这种情况产生的根本原因是,Servlet处理完请求以后,直接转发到目标页面.    - 这样整一个业务,只发送了一次请求,那么当你在浏览器中点击刷新按钮或者狂按f5会一直都会刷新之前的请求 解决方案:     使用重定向跳转到目标页面 第二种情况:    在提交表单时,如果网速较差,可能会导致点击提交按钮多次,这种情况也会导致表单重复提交.    - 产生的原因:是

form表单重复提交问题

导致表单重复提交的原因是:第一次提交的表单会被缓存到内存中,直到页面下次提交或页面关闭或转向其他页面时才消失.在自调用返回时,内存中的数据依然在,这时页面中的判断提交的代码依然可以检测到提交的值,顾会产生重复提交的效果. 解决方法 Ⅰ重定向,页面提交后转到另一个页面而不是本页面 Ⅱ提交表单后提交按钮变灰/隐藏提交按钮 Ⅲ增加令牌token 访问页面前产生token public void toStart(HttpServletRequest req, HttpServletResponse re

如何防止表单重复提交

一.有很多的应用场景都会遇到重复提交问题,比如: 1.点击提交按钮两次.2.点击刷新按钮.3.使用浏览器后退按钮重复之前的操作,导致重复提交表单.4.使用浏览器历史记录重复提交表单.5.浏览器重复的 HTTP 请求. 二.防止表单重复提交的方法 1.禁掉提交按钮 表单提交后使用 Javascript 使提交按钮disable.这种方法防止心急的用户多次点击按钮.但有个问题,如果客户端把 Javascript 给禁止掉,这种方法就无效了. 2.Post/Redirect/Get 模式 在提交后执行

防表单重复提交

防表单重复提交 1.令牌生成器 import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.Random; import sun.misc.BASE64Encoder; public class TokenProccessor { /* *单例设计模式(保证类的对象在内存中只有一个) *1.把类的构造函数私有 *2.自己创建一个类的对象 *3.对外提供一个公