`
369540808
  • 浏览: 204327 次
文章分类
社区版块
存档分类
最新评论

避免表单的重复提交

 
阅读更多

一、在客户端避免表单的重复提交

在客户端我们可以用JS脚本来控制表单提交的次数,首先定义一个为true的变量,点击一次过后就置为false来关闭提交。实现如下:

<%@ page contentType="text/html;charset=GBK" %>
<html>
<head>
<title>登录页面</title>
<script language="javascript">
var checkSubmitFlg=true;
function checkSubmit(){
if(true==checkSubmitFlg){
document.theForm.btnSubmit.disabled=true; //将按钮置灰
document.theForm.submit();
checkSubmitFlg=false;
} else {
alert("你已经提交了表单,请不要重复提交!");
}
}
</script>
</head>
<body>
<form method="post" action="handler" name="theForm">
<table>
<tr><td>用户名:</td><td><input type="text" name="username"></td></tr>
<tr><td>邮件地址:</td><td><input type="text" name="email"></td></tr>
<tr><td><input type="reset" value="重填"></td>
<td><input type="button" name="btnSubmit" value="提交" onClick="checkSubmit();"/></td></tr>
</table>
</form>
</body>
</html>

这种方法的优点是简单方便,但当用户刷新页面或者是点了回退按钮的时候请求将会再次提交。

二、在服务器避免表单的重复提交

在服务器我们可以利用同步令牌避免表单的重复提交,首先当用户第一次提交数据,创建一个Session对象,并产生一个令牌值,将这个令牌值作为隐藏输入域发送到客户端,同时将令牌值保存在Session中。第二次提交页面的时候,服务器首先判断请求参数中的令牌值和Session中保存的令牌值是否相等,如果相等则处理,如果不相等,则提示用户已提交过表单。Struts中给出了一个TokenProcessor单例类实现同步令牌,根据它编写了一个TokenProcessor类如下:

1. TokenProcessor.java实现

package test;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
/**
* TokenProcessor类是一个单例类。
*/
public class TokenProcessor{
static final String TOKEN_KEY="jiang.token";
private static TokenProcessor instance = new TokenProcessor();
/**
* getInstance()方法得到单例类的实例。
*/
public static TokenProcessor getInstance(){
return instance;
}
/**
* 最近一次生成令牌值的时间戳。
*/
private long previous;
/**
* 判断请求参数中的令牌值是否有效。
*/
public synchronized boolean isTokenValid(HttpServletRequest request){
//得到请求的当前Session对象。
HttpSession session = request.getSession(false);
if (session == null){
return false;
}
//从Session中取出保存的令牌值。
String saved = (String) session.getAttribute(TOKEN_KEY);
if (saved == null) {
return false;
}
//清除Session中的令牌值。
resetToken(request);
//得到请求参数中的令牌值。
String token = request.getParameter(TOKEN_KEY);
if (token == null) {
return false;
}
return saved.equals(token);
}
/**
* 清除Session中的令牌值。
*/
public synchronized void resetToken(HttpServletRequest request){
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(TOKEN_KEY);
}
/**
* 产生一个新的令牌值,保存到Session中,
* 如果当前Session不存在,则创建一个新的Session。
*/
public synchronized void saveToken(HttpServletRequest request){
HttpSession session = request.getSession();
String token = generateToken(request);
if (token != null) {
session.setAttribute(TOKEN_KEY, token);
}
}
/**
* 根据用户会话ID和当前的系统时间生成一个唯一的令牌。
*/
public synchronized String generateToken(HttpServletRequest request){
HttpSession session = request.getSession();
try{
byte id[] = session.getId().getBytes();
long current = System.currentTimeMillis();
if (current == previous){
current++;
}
previous = current;
byte now[] = new Long(current).toString().getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(id);
md.update(now);
return toHex(md.digest());
}catch (NoSuchAlgorithmException e){
return null;
}
}
/**
* 将一个字节数组转换为一个十六进制数字的字符串。
*/
private String toHex(byte buffer[]){
StringBuffer sb = new StringBuffer(buffer.length * 2);
for (int i = 0; i < buffer.length; i++){
sb.append(Character.forDigit((buffer[i] & 0xf0) >> 4, 16));
sb.append(Character.forDigit(buffer[i] & 0x0f, 16));
}
return sb.toString();
}
/**
* 从Session中得到令牌值,如果Session中没有保存令牌值,则生成一个新的令牌值。
*/
public synchronized String getToken(HttpServletRequest request){
HttpSession session = request.getSession(false);
if(null==session)
return null;
String token=(String)session.getAttribute(TOKEN_KEY);
if(null==token){
token = generateToken(request);
if (token != null){
session.setAttribute(TOKEN_KEY, token);
return token;
} else
return null;
}
else
return token;
}
}
2. 测试页面index.jsp

<%@ page contentType="text/html;charset=GBK" %>
<%@ page import="test.TokenProcessor" %>
<html>
<head><title>登录页面</title></head>
<body>
<%
TokenProcessor processor=TokenProcessor.getInstance();
String token=processor.getToken(request);
%>
<form method="post" action="handler" name="theForm">
<table>
<tr><td>用户名:</td><td><input type="text" name="username"></td></tr>
<tr><td>邮件地址:</td><td> <input type="text" name="email">
<input type="hidden" name="jiang.token" value="<%=token%>"/></td></tr>
<tr><td><input type="reset" value="重填"></td> <td><input type="submit" value="提交"></td></tr>
</table>
</form>
</body>
</html>

3. 测试Servlet,HandlerServlet.java

package test;
import javax.servlet.*;
import java.io.*;
import javax.servlet.http.*;
import test.TokenProcessor;
public class HandlerServlet extends HttpServlet{
int count=0;
public void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException,IOException {
resp.setContentType("text/html;charset=GBK");
PrintWriter out=resp.getWriter();
TokenProcessor processor=TokenProcessor.getInstance();
if(processor.isTokenValid(req)){
try{
Thread.sleep(5000);
}catch(InterruptedException e){
System.out.println(e);
}
System.out.println("submit : "+count);
if(count%2==1)
count=0;
else
count++;
out.println("success");
} else{
processor.saveToken(req);
out.println("你已经提交了表单,同一表单不能提交两次。");
}
out.close();
}
}

分享到:
评论

相关推荐

    SSH笔记-数据验证、上传下载、避免表单重复提交、自定义拦截器

    接着,我们讨论如何避免表单重复提交。在Web应用中,用户可能无意或有意地多次点击提交按钮,导致数据库中出现重复数据。为了防止这种情况,通常会在服务器端或客户端采取措施。在Struts2中,可以使用Session来存储...

    防止Layui form表单重复提交的实现方法

    下面详细解释几种防止Layui表单重复提交的方法。 首先,在HTML表单中,为了避免在提交时页面刷新导致的重复提交,可以在标签中使用onsubmit="return false;"属性。这个属性的作用是在表单提交时返回false,阻止...

    javascript方式防止表单重复提交

    在Web开发中,表单重复提交是一个常见的问题,可能导致数据的冗余或错误。JavaScript作为客户端脚本语言,可以通过多种策略来防止用户意外或恶意地多次提交表单。以下是一些关键的知识点: 1. **禁用提交按钮**:最...

    [Jsp]防止页面表单重复提交的解决方法

    本篇文章将探讨如何有效地防止JSP页面中的表单重复提交,确保系统的稳定性和数据的准确性。 一、理解表单重复提交的问题 当用户点击提交按钮后,由于网络延迟或浏览器刷新等原因,可能导致同一份表单数据多次发送...

    springboot2.1+redis+拦截器 防止表单重复提交

    在现代Web应用开发中,防止表单重复提交是一项重要的任务,因为这可能导致数据不一致性和服务器资源浪费。本文将深入探讨如何使用Spring Boot 2.1、Redis和拦截器来实现这一功能。以下是对这个主题的详细解释: ...

    Struts2解决表单重复提交

    在Web应用中,表单重复提交是一种常见的问题。通常,这种问题发生在用户在提交表单后,由于网络延迟或用户的误操作再次点击提交按钮,或者在表单提交后刷新浏览器页面。这两种情况都可能导致服务器接收到重复的请求...

    防止表单重复提交(asp.net )

    在ASP.NET web应用程序中,表单重复提交是一个常见的问题,可能导致数据不一致或者数据库操作的冗余。为了确保用户在提交表单时不会无意或有意地多次发送请求,我们需要实施有效的防止表单重复提交的策略。以下是...

    用Struts的Token机制解决表单重复提交.doc

    通过上述介绍可以看出,Struts的Token机制提供了一种简单而有效的解决方案来避免表单重复提交的问题。开发者只需要遵循一定的编码规范和逻辑结构,就可以轻松地在自己的项目中实现这一机制。这对于提高Web应用的数据...

    防止表单重复提交

    然而,如果没有适当处理,可能会出现表单重复提交的问题,这可能导致数据的不一致性和服务器资源的浪费。本篇文章将深入探讨如何防止表单重复提交,主要关注于基于Struts2框架的解决方案。 首先,理解表单重复提交...

    Java web解决表单重复提交问题

    3.什么情况需要避免表单重复提交?  什么叫表单提交问题,说白了,是同一份信息,重复的提交给服务器。  那么,在什么情况下回产生表单重复提交的情况呢?  给大家列举以下情况:  1.点击F5刷新页面:当用户...

    表单重复提交问题1

    在Web开发中,表单重复提交是一个常见的问题,它可能会导致数据冗余或者不一致,尤其是在处理关键操作如交易、订单或用户注册时。这里我们深入探讨这个问题,并提供解决方案。 标题"表单重复提交问题1"所涉及的核心...

    Struts之Token解决表单那重复提交

    表单重复提交可能发生在用户点击提交按钮后,由于网络延迟或刷新页面等原因,导致请求被多次发送到服务器。如果不加以控制,可能会导致同一份数据被处理多次,从而对数据库造成不必要的影响。 二、Token机制的原理 ...

    ASP.NET中防止刷新页面造成表单重复提交

    ### ASP.NET中防止刷新页面造成表单重复提交 在Web应用程序开发中,特别是在使用ASP.NET进行网站构建时,一个常见的问题是表单重复提交。这通常发生在用户通过按下浏览器的F5键来刷新页面的情况下,此时之前的表单...

    试谈在Web应用中如何避免表单的重复提交.pdf

    如何避免Web应用中的表单重复提交 在Web应用中,避免表单的重复提交是一个棘手的问题。用户在提交表单时可能因为网络速度的原因,或者网页被恶意刷新,导致同一条记录重复插入到数据库中。这篇文章将探讨如何从...

    java实现防止表单重复提交

    服务器端避免表单的重复提交,利用同步令牌来解决重复提交的基本原理如下:(1)用户访问提交数据的页面,服务器端在这次会话中,创建一个session对象,并产生一个令牌值,将这个令牌值作为隐藏输入域的值,随表单一起发送到...

    使用struts的同步令牌避免form的重复提交

    ### 使用Struts的同步令牌避免表单重复提交 #### 一、使用方法 为了有效地防止Web应用程序中的表单重复提交问题,Struts框架提供了一种简单而强大的解决方案——同步令牌模式(Synchronization Token Pattern, STP...

    element-ui如何防止重复提交的方法步骤

    在IT行业中,尤其是在前端开发领域,防止用户重复提交是一项重要的任务,这有助于避免因网络延迟或用户误操作导致的数据混乱。Element-UI,一个流行的Vue.js组件库,提供了多种方式来处理这个问题。以下是如何在使用...

    spring boot 防止重复提交实现方法详解

    Spring Boot 防止重复提交是指在用户提交表单或请求时,防止同一客户端在短时间内对同一 URL 的重复提交,从而避免服务器端的处理压力和数据的一致性问题。下面将详细介绍 Spring Boot 防止重复提交实现方法的相关...

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

    PHP作为常用的服务器端脚本语言,提供多种方式来处理和避免表单重复提交的问题。以下将详细介绍几种常用的方法: 1. **利用JavaScript禁用提交按钮** 当用户点击提交按钮后,通过JavaScript将按钮设置为禁用状态,...

Global site tag (gtag.js) - Google Analytics