Struts
的
Token
(令牌)机制能够很好的解决表单重复提交的问题,基本原理是:服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
这时其实也就是两点,第一:你需要在请求中有这个令牌值,请求中的令牌值如何保存,其实就和我们平时在页面中保存一些信息是一样的,通过隐藏字段来保存,保存的形式如:
〈
input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"
〉,这个
value
是
TokenProcessor
类中的
generateToken()
获得的,是根据当前用户的
session id
和当前时间的
long
值来计算的。第二:在客户端提交后,我们要根据判断在请求中包含的值是否和服务器的令牌一致,因为服务器每次提交都会生成新的
Token
,所以,如果是重复提交,客户端的
Token
值和服务器端的
Token
值就会不一致。下面就以在数据库中插入一条数据来说明如何防止重复提交。
在
Action
中的
add
方法中,我们需要将
Token
值明确的要求保存在页面中,只需增加一条语句:
saveToken(request);
,如下所示:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
//
前面的处理省略
saveToken(request);
return mapping.findForward("add");
}
在
Action
的
insert
方法中,我们根据表单中的
Token
值与服务器端的
Token
值比较,如下所示:
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
if (isTokenValid(request, true)) {
//
表单不是重复提交
//
这里是保存数据的代码
} else {
//
表单重复提交
saveToken(request);
//
其它的处理代码
}
}
其实使用起来很简单,举个最简单、最需要使用这个的例子:
一般控制重复提交主要是用在对数据库操作的控制上,比如插入、更新、删除等,由于更新、删除一般都是通过
id
来操作(例如:
updateXXXById, removeXXXById
),所以这类操作控制的意义不是很大(不排除个别现象),重复提交的控制也就主要是在插入时的控制了。
先说一下,我们目前所做项目的情况:
目前的项目是用
Struts
+
Spring
+
Ibatis
,页面用
jstl
,
Struts
复杂
View
层,
Spring
在
Service
层提供事务控制,
Ibatis
是用来代替
JDBC
,所有页面的访问都不是直接访问
jsp
,而是访问
Structs
的
Action
,再由
Action
来
Forward
到一个
Jsp
,所有针对数据库的操作,比如取数据或修改数据,都是在
Action
里面完成,所有的
Action
一般都继承
BaseDispatchAction
,这个是自己建立的类,目的是为所有的
Action
做一些统一的控制,在
Struts
层,对于一个功能,我们一般分为两个
Action
,一个
Action
里的功能是不需要调用
Struts
的验证功能的(常见的方法名称有
add,edit,remove,view,list
),另一个是需要调用
Struts
的验证功能的(常见的方法名称有
insert,update
)。
就拿论坛发贴来说吧,论坛发贴首先需要跳转到一个页面,你可以填写帖子的主题和内容,填写完后,单击
“
提交
”
,贴子就发表了,所以这里经过两个步骤:
1
、转到一个新增的页面,在
Action
里我们一般称为
add
,例如:
public ActionForward add(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
//
这一句是输出调试信息,表示代码执行到这一段了
log.debug(":: action - subject add");
//your code here
//
这里保存
Token
值
saveToken(request);
//
跳转到
add
页面,在
Structs-config.xml
里面定义,例如,跳转到
subjectAdd.jsp
return mapping.findForward("add");
}
2
、在填写标题和内容后,选择
提交
,会提交到
insert
方法,在
insert
方法里判断,是否重复提交了。
public ActionForward insert(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response){
if (isTokenValid(request, true)) {
//
表单不是重复提交
//
这里是保存数据的代码
} else {
//
表单重复提交
saveToken(request);
//
其它的处理代码
}
}
下面更详细一点(注意,下面所有的代码使用全角括号):
1
、你想发贴时,点击
“
我要发贴
”
链接的代码可以里这样的:
〈
html:link action="subject.do?method=add"
〉我要发贴〈
/html:link
〉
subject.do
和
method
这些在
struct-config.xml
如何定义我就不说了,点击链接后,会执行
subject.do
的
add
方法,代码如上面说的,跳转到
subjectAdd.jsp
页面。页面的代码大概如下:
〈
html:form action="subjectForm.do?method=insert"
〉
〈
html:text property="title" /
〉
〈
html:textarea property="content" /
〉
〈
html:submit property="
发表
" /
〉
〈
html:reset property="
重填
" /
〉
〈
html:form
〉
如果你在
add
方法里加了
“saveToken(request);”
这一句,那在
subjectAdd.jsp
生成的页面上,会多一个隐藏字段,类似于这样〈
input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"
〉,
2
、点击发表后,表单提交到
subjectForm.do
里的
insert
方法后,你在
insert
方法里要将表单的数据插入到数据库中,如果没有进行重复提交的控制,那么每点击一次浏览器的刷新按钮,都会在数据库中插入一条相同的记录,增加下面的代码,你就可以控制用户的重复提交了。
if (isTokenValid(request, true)) {
//
表单不是重复提交
//
这里是保存数据的代码
} else {
//
表单重复提交
saveToken(request);
//
其它的处理代码
}
注意,你必须在
add
方法里使用了
saveToken(request)
,你才能在
insert
里判断,否则,你每次保存操作都是重复提交。
记住一点,
Struts
在你每次访问
Action
的时候,都会产生一个令牌,保存在你的
Session
里面,如果你在
Action
里的函数里面,使用了
saveToken(request);
,那么这个令牌也会保存在这个
Action
所
Forward
到的
jsp
所生成的静态页面里。
如果你在你
Action
的方法里使用了
isTokenValid
,那么
Struts
会将你从你的
request
里面去获取这个令牌值,然后和
Session
里的令牌值做比较,如果两者相等,就不是重复提交,如果不相等,就是重复提交了。
由于我们项目的所有
Action
都是继承自
BaseDispatchAction
这个类,所以我们基本上都是在这个类里面做了表单重复提交的控制,默认是控制
add
方法和
insert
方法,如果需要控制其它的方法,就自己手动写上面这些代码,否则是不需要手写的,控制的代码如下:
public abstract class BaseDispatchAction extends BaseAction {
protected ActionForward perform(ActionMapping mapping, ActionForm form,
HttpServletRequest request, HttpServletResponse response)
throws Exception {
String parameter = mapping.getParameter();
String name = request.getParameter(parameter);
if (null == name) { //
如果没有指定
method
,则默认为
list
name = "list";
}
if ("add".equals(name)) {
if ("add".equals(name)) {
saveToken(request);
}
} else if ("insert".equals(name)) {
if (!isTokenValid(request, true)) {
resetToken(request);
saveError(request, new ActionMessage("error.repeatSubmit"));
log.error("
重复提交!
");
return mapping.findForward("error");
}
}
return dispatchMethod2(mapping, form, request, response, name);
}
}
分享到:
相关推荐
在你提供的压缩包文件"token"中,可能包含了一个简单的Struts2令牌实例,你可以通过查看源代码学习如何在实际项目中集成和使用令牌机制。学习和理解这个实例,将有助于你更好地理解和应用Struts2的令牌功能。
在Struts框架中,令牌机制(Token)是一种防止重复提交的有效方法,它主要用于处理表单数据的并发控制,防止用户意外或者恶意地多次提交表单,从而确保数据的一致性和安全性。 在Web应用中,用户可能会因为网络延迟...
在提供的压缩包文件"struts+token机制解决表单重复提交"中,可能包含了具体的Struts配置文件、Action类、Interceptor实现以及示例代码,可以帮助读者更深入地理解并实践这个机制。通过对这些代码的学习和研究,...
Struts的Token机制是Web应用中防止表单重复提交的一种常用方法。在处理表单提交时,如果用户意外地多次点击了提交按钮,可能会导致数据的重复录入,从而引起不必要的问题,例如订单重复、数据库数据异常等。为了解决...
而Struts2的Token机制要求每个提交都带有服务器生成的唯一令牌,这使得伪造表单无法通过验证,从而有效地防御了CSRF攻击。 **四、Struts2 Token配置** 在Struts2中,可以通过配置Action或者全局Interceptor来启用...
而Struts1.x的令牌机制(Token)则是防止重复提交、跨页请求攻击的重要手段。在此,我们将深入探讨Struts1.x令牌的使用方法及其背后的原理。 首先,理解为何需要令牌。在Web应用中,用户可能会意外或恶意地多次点击...
Struts Token机制的核心思想是在客户端(浏览器)和服务器端(应用服务器)之间维持一个唯一的令牌(Token)。当用户首次提交表单时,服务器会生成一个随机的、唯一标识的Token,并将其存储到用户的会话(Session)...
Struts2的令牌机制是其防止重复提交和CSRF(跨站请求伪造)攻击的一种重要安全策略。在Web开发中,尤其是使用MVC框架如Struts2时,确保用户请求的唯一性和安全性至关重要。令牌机制就是这样的一个工具,它通过在表单...
Struts2提供了一种名为“token”的机制来解决这个问题。 **什么是Token机制?** Token机制是一种防止重复提交的方法,它通过在客户端(通常是浏览器的session或者cookie)和服务器端存储一个唯一的令牌,确保每个...
#### 一、Struts令牌机制简介 Struts框架通过生成一个唯一的令牌(Token),并在每次用户提交表单时验证该令牌的有效性,以此来防止重复提交。这种机制可以确保即使用户多次点击提交按钮或者浏览器回退后重新提交...
本文将深入探讨如何在Struts框架中利用Token机制来解决这个问题。 一、表单重复提交问题 表单重复提交可能发生在用户点击提交按钮后,由于网络延迟或刷新页面等原因,导致请求被多次发送到服务器。如果不加以控制,...
### Struts2令牌机制详解 #### 一、Struts2令牌机制概述 在Web应用程序开发过程中,为了防止重复提交表单或CSRF(跨站请求伪造)等安全问题,Struts2框架提供了一种名为“令牌”的机制。该机制通过在用户会话中...
在处理表单提交时,为了防止重复提交或者跨站请求伪造(CSRF)攻击,Struts2引入了令牌机制。这个"struts2 令牌使用例子"是一个很好的实践教程,帮助开发者理解如何在实际应用中实施这一安全策略。 首先,我们需要...
为了避免这种情况,Struts2引入了令牌(Token)机制。 令牌机制的工作原理是这样的: 1. 当用户访问一个需要防重提交的页面时,服务器会生成一个唯一的令牌,并将其存储到用户的session中。 2. 这个令牌会被嵌入到...
Struts2提供了一种称为“令牌”或“Token Session”的机制来解决这个问题。 令牌机制的工作原理是,在用户提交表单前,服务器会生成一个唯一的令牌,并将其添加到表单中隐藏字段或者放入session。当用户提交表单时...
Token机制是一种防止重复提交的方法,它通过在客户端(通常是浏览器)和服务器之间交换一个唯一的、一次性使用的令牌来确保请求的独特性。当用户提交表单时,服务器会生成一个随机的Token并将其存储到会话(Session...
二、Struts令牌的实现步骤 1. 添加Struts令牌拦截器 在Struts的配置文件(通常为struts.xml)中,需要添加`token`和`tokenSession`拦截器到默认的拦截器栈。`token`拦截器负责在表单请求时生成和验证令牌,`token...
Token机制是一种有效的防护手段,它通过在表单中添加一个唯一的、随机的令牌值,并在服务器端验证这个令牌来确保请求的合法性。以下是对Struts1.x中使用Token防止提交的详细说明: 1. **理解Token机制**: Token...