平时网上注册大家都经历过,比如用户在注册成功之后,再打击后退按钮,退回到表单页再次提交表单,如果未处理重复提交这一细节上的要求,将会再次成功提交,数据库中有重复数据,在一个良好的程序中式不允许这么出现的。
Struts的Token(令牌)机制能够很好的解决表单重复提交的问题。
基本原理是:服务器在处理到达的请求之前,会将请求中包含令牌值与保存在当前会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在相应发送给客户端之前,将会产生一个新的令牌值,该令牌值除传给客户端以外,也会将用户会话中的令牌值进行替换,这样如果用户后退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效的防止了重复提交的发生
用户在使用时要注意一下两点:
第一、用户需要在请求中包含这个令牌值,请求中的令牌值如何保存,其实就和平时在页面中保存一些信息是一样的,通过隐藏域来保存,保存的形式如:<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae" >,这个value是TokenProcessor类中的generateToken()获得的,是根据当前用户的session id 和当前时间的long值计算的
第二、在客户端提交后,要判断在请求中包含的值是否和服务器的令牌一直,因为服务器每次提交都会生成新的Token,所以,如果是重复提交,客户端的Token值和服务器端的Token值就会不一致
示例
index.jsp
<%@ page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Struts应用:利用Token防止重复提交</title>
</head>
<body>
<h3>利用Token防止重复提交</h3><hr/>
<a href="user.do?method=toAdd">添加用户</a>
</body>
</html>
addUser.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://struts.apache.org/tags-html" prefix="html" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>添加用户</title>
<meta http-equiv="pragma" content="no-cache">
<meta http-equiv="cache-control" content="no-cache">
<meta http-equiv="expires" content="0">
<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
<meta http-equiv="description" content="This is my page">
<!--
<link rel="stylesheet" type="text/css" href="styles.css">
-->
</head>
<body>
<h3>添加用户</h3>
<html:form action="user.do?method=add" method="post">
<table border="1" width="600px">
<tr>
<td>登录名</td>
<td><input type="text" name="loginname"/></td>
</tr>
<tr>
<td>密码</td>
<td><input type="password" name="pwd"/></td>
</tr>
<tr>
<td colspan="2" align="center">
<input type="submit" value="提交"/>
<input type="reset" value="重置"/>
</td>
</tr>
</table>
</html:form>
</body>
</html>
login_success.jsp
<%@ page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登录成功</title>
</head>
<body>
<h3>登录成功</h3><hr/>
<h2>欢迎:${param.loginname}登录!</h2>
</body>
</html>
login_failure.jsp
<%@ page pageEncoding="UTF-8"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登录失败</title>
</head>
<body>
<h3>登录失败</h3><hr/>
<h2 style="color:red">可能的原因是:${errorMsg}</h2>
</body>
</html>
LoginForm.java
package com.javacrazyer.web.formbean;
import javax.servlet.http.HttpServletRequest;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionMapping;
/**
* 用来收集客户端提交数据.
* 要收集数据的属性的名一定要跟请求参数名相同
*/
public class LoginForm extends ActionForm {
public ActionErrors validate(ActionMapping mapping,
HttpServletRequest request) {
return null;
}
private static final long serialVersionUID = 6619272689058619128L;
private String loginname;
private String pwd;
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getPwd() {
return pwd;
}
public void setPwd(String pwd) {
this.pwd = pwd;
}
}
LoginAction.java
package com.javacrazyer.web.action;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.apache.struts.actions.DispatchAction;
/**
* 业务控制器:控制业务处理的流程
*
*/
public class LoginAction extends DispatchAction {
//具体业务流程处理方法,由Struts框架回调
public ActionForward toAdd(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//产生Token值并存储到session中
this.saveToken(request);
return mapping.findForward("toadd");
}
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
if(this.isTokenValid(request)){
this.saveToken(request);
System.out.println("往数据库添加数据...");
return mapping.findForward("succ");
}else{
System.out.println("请不要重复提交数据.....");
return mapping.findForward("failure");
}
}
}
WEB-INF/struts-config.xml
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts-config PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
"http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
<struts-config>
<!-- ================================================ Form Bean Definitions
-->
<form-beans>
<form-bean name="loginForm" type="com.javacrazyer.web.formbean.LoginForm"/>
</form-beans>
<!-- =========================================== Action Mapping Definitions
-->
<action-mappings>
<action path="/user" name="loginForm" type="com.javacrazyer.web.action.LoginAction"
parameter="method">
<forward name="toadd" path="/adduser.jsp"/>
<forward name="succ" path="/login_success.jsp"/>
<forward name="failure" path="/login_failure.jsp"/>
</action>
</action-mappings>
</struts-config>
具体页面的流程为
这时如果点击后退那个箭头,再提交的话那么就是重复提交了,控制台多出现一条‘请不要重复提交数据’的输出信息
解释下这个流程:
首先是点击添加用户,跳到登录页面,这个过程调用了LoginAction.java中的toadd方法,这个方法中正好有个
saveToken(request)方法,那么这就说明了要将这步请求的TOKEN值保存在会话中,这样跳到登陆页面的话,登录页面会多出一个隐藏表单类似于上面说的<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae" >,点击登录后那么就会出现将登录页面请求中包含的TOKEN值跟会话中的TOKEN值对比的情况,如果通过就提交成功。这样处理过后那么就会产生新的令牌值,会话中的令牌值也将改变,因此当点击最后页面的后退在提交时,页面的TOKEN值与会话中的已经不一样了,所以就避免了重复提交
- 大小: 11.5 KB
- 大小: 13.7 KB
- 大小: 12.2 KB
- 大小: 8.4 KB
分享到:
相关推荐
在 Struts 中,"重复提交 token" 是一个重要的概念,用于防止用户意外或恶意地多次提交同一个表单,从而确保数据的一致性和安全性。 在 Web 应用中,重复提交问题可能出现在用户网络不稳定或误操作的情况下,导致同...
### 利用Token机制解决重复提交问题 在Web应用开发中,防止表单的重复提交是一个常见的需求。本文将深入探讨如何通过Token机制来解决这一问题,并提供详细的实现步骤及原理解析。 #### 一、Token机制简介 Token...
总结,Struts2的tokenSession机制是JavaEE Web开发中防止重复提交的有效手段,通过生成并校验token,确保每个请求的唯一性,从而保护了业务数据的完整性。在实际项目中,我们需要正确配置和使用这个机制,以提高应用...
Java开发案例-springboot-34-整合Sa-Token实现权限认证-源代码+文档.rar Java开发案例-springboot-34-整合Sa-Token实现权限认证-源代码+文档.rar Java开发案例-springboot-34-整合Sa-Token实现权限认证-源代码+文档....
### 解决Struts中通过Token防止重复提交的问题 在Web应用程序开发中,特别是基于MVC架构的框架如Apache Struts中,确保用户操作的安全性是非常重要的。其中一项常见且重要的安全措施是防止表单的重复提交。本文将...
Java开发案例-springboot-整合Sa-Token-Quick-Login插件实现快速登录认证-源代码+文档.rar Java开发案例-springboot-整合Sa-Token-Quick-Login插件实现快速登录认证-源代码+文档.rar Java开发案例-springboot-整合Sa...
总的来说,Struts Token机制通过维护一个临时的、一次性使用的Token,有效地解决了Web应用中的表单重复提交问题,提高了系统的稳定性和安全性。在实际开发中,应根据项目需求灵活运用并优化此机制。
本话题将探讨如何在Struts 1.2中利用Token机制来解决HTTP请求的重复提交问题,这是一种常见的防止用户意外或恶意多次点击提交按钮导致数据异常的策略。 一、重复提交问题 在Web应用中,如果一个表单被用户意外或者...
struts2防止表单重复提交,利用struts的拦截器tokenSession,轻轻松松解决表单重复提交的问题。 附件为源代码,后台延迟了3秒,可直接在web服务器下部署运行,输入用户名和密码后,多点几次提交按钮,然后看控制台...
Struts的Token机制主要用来防止用户意外或恶意的多次提交表单,例如在刷新页面时重复提交数据。它的工作原理如下: 1. **生成Token**: 当用户访问一个需要防重复提交的表单时,服务器会生成一个唯一的Token并将其...
在Struts配置文件中,为需要防止重复提交的Action添加一个拦截器引用,如`token`或`token-session`。这两个拦截器都可以处理Token,但`token-session`更安全,因为它会将Token存储在会话中,而不仅仅是请求中。 2....
在提供的压缩包文件"struts+token机制解决表单重复提交"中,可能包含了具体的Struts配置文件、Action类、Interceptor实现以及示例代码,可以帮助读者更深入地理解并实践这个机制。通过对这些代码的学习和研究,...
在"google-translate-token-master"压缩包中,通常包含了库的源码、示例、文档等资源。开发者可以查看源码了解其工作原理,或者参考示例快速上手使用。此外,阅读文档可以帮助理解库的配置选项和可能遇到的问题。 ...
### 使用Struts Token机制解决表单重复提交 #### 一、引言 在Web应用程序开发过程中,表单重复提交是一个常见的问题。用户可能因为网络延迟、浏览器缓存等原因导致重复点击提交按钮,进而向服务器发送多个相同的...
Struts2是一个非常流行的Java Web框架,用于构建和维护可扩展且易于管理的企业级应用...综上所述,Struts2的Token机制是防止Web应用中重复提交的有效工具,通过合理的配置和编程,可以为用户的操作提供更安全的环境。
在IT行业中,地图服务是许多应用的核心组成部分,Mapbox GL是一个流行的地图渲染库,它提供了交互式、高性能的2D和3D地图...同时,随着技术的发展,Mapbox和其他类似服务可能提供新的解决方案,让去token变得更加简便。
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
总的来说,Struts2的`token`拦截器是防止重复提交的有效解决方案,通过结合合理的拦截器配置和跳转策略,可以确保应用程序的稳定性和数据一致性。在实际开发中,还需要考虑其他因素,如异常处理、用户体验优化等,以...
### Struts Token机制防止页面刷新及重复提交 在Web应用开发过程中,特别是在使用MVC框架如Apache Struts进行开发时,防止表单重复提交是一个重要的安全措施。表单重复提交通常发生在用户点击“提交”按钮后,由于...