struts1避免重复提交

一、使用方法

1、  假如你要提交的页面为toSubmit.jsp;

2、  在打开toSubmit.jsp的Action1中加入:saveToken(request),例如

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
//生成同步令牌
saveToken(request);
return mapping.findForward("toSubmit");
}

3、  在提交toSubmit.jsp的Action2中加入:isTokenValid(request, true),例如:

public ActionForward execute(
ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// 验证同步令牌
if (isTokenValid(request, true)) {
//执行提交操作
}else {
// 重复提交
return mapping.findForward("Error");
}
}

4、  使用注意:toSubmit.jsp中的form必须使用struts的标签<html:form>。

二、基本原理

第一步、在session中放入同步令牌

在Action1中加入了saveToken(request)的方法后,调用TokenProcessor类的saveToken方法如下:

public synchronized void saveToken(HttpServletRequest request) {
HttpSession session = request.getSession();
String token = generateToken(request);
if (token != null) {
session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token);
}
}

很明显在session中放入了同步令牌,名称为Globals.TRANSACTION_TOKEN_KEY。

第二步、在页面创建hidden元素

当应用服务器初始化toSubmit.jsp页面遇到标签<html:form>时,便会调用struts的FormTag类,其中有一个方法:

protected String renderToken() {
StringBuffer results = new StringBuffer();
HttpSession session = pageContext.getSession(); if (session != null) {
String token =
(String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY); if (token != null) {
results.append("<input type=\"hidden\" name=\"");
results.append(Constants.TOKEN_KEY);
results.append("\" value=\"");
results.append(token);
if (this.isXhtml()) {
results.append("\" />");
} else {
results.append("\">");
}
}
} return results.toString();
}

其意为:当检测到session中的Globals.TRANSACTION_TOKEN_KEY不为空时,在toSubmit.jsp页面创建元素:

<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="">

名称为:org.apache.struts.taglib.html.TOKEN就是Constants.TOKEN_KEY;

值为:session中的Globals.TRANSACTION_TOKEN_KEY的值,即为同步令牌值。

第三步、验证同步令牌

在Action2中加入isTokenValid方法,实际上是调用TokenProcessor类的isTokenValid方法如下:

public synchronized boolean isTokenValid(
HttpServletRequest request,
boolean reset) { // Retrieve the current session for this request
HttpSession session = request.getSession(false);
if (session == null) {
return false;
} // Retrieve the transaction token from this session, and
// reset it if requested
String saved = (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
if (saved == null) {
return false;
} if (reset) {
this.resetToken(request);
} // Retrieve the transaction token included in this request
String token = request.getParameter(Constants.TOKEN_KEY);
if (token == null) {
return false;
} return saved.equals(token);
}

它首先取得session中的令牌值,然后resetToken,再从页面hidden元素取来令牌值,进行比较,如果相等则为第一次,不等则为重复提交。

其中resetToken方法如下:

public synchronized void resetToken(HttpServletRequest request) {
HttpSession session = request.getSession(false);
if (session == null) {
return;
}
session.removeAttribute(Globals.TRANSACTION_TOKEN_KEY);
}

struts2避免重复提交

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

首先需要在表单中使用

<s:token name="user.token"></s:token>

<s:token>标签创建一个新的令牌值,并用你所指定的令牌名把令牌保存到session中。而这个令牌值是随即产生的经过加密的字符序列,不会重复。struts2使用拦截器来检查表单是否重复提交,它采用同步令牌的方式来实现对表单重复提交的判断。

其次需要为action配置TokenInterceptor或者TokenSessionStoreInterceptor拦截器。这两个拦截器都已经在struts-default.xml中定义,但没有包含在defaultStack拦截器栈中。

1、使用TokenInterceptor在action中配置拦截器和在重复提交时,将要请求导向的结果视图。

<action name="register" class="com.zhaosoft.action.RegisterAction">
<!-- 配置异常映射,当RegisterAction抛出Exception异常时,向用户显示error.jsp页面 -->
<exception-mapping result="error" exception="java.lang.Exception"/>
<result name="invalid.token">/WEB-INF/pages/register.jsp</result>
<result name="input">/WEB-INF/pages/register.jsp</result>
<result name="success">/WEB-INF/pages/success.jsp</result>
<result name="error">/WEB-INF/pages/error.jsp</result>
<interceptor-ref name="defaultStack">
<param name="workflow.excludeMethods">default</param>
</interceptor-ref>
<interceptor-ref name="token">
<param name="excludeMethods">default</param>
</interceptor-ref>
</action>

注:excludeMethods指定要排除的方法。

在register.jsp页面中添加action级别的错误信息显示的标签:<s:actionerror/>

在form中添加<s:token>标签:<s:token name="user.token"></s:token>

最好为在资源文件中设置键struts.messages.invalid.token的本地化消息。

struts.messages.invalid.token=您已经提交了表单,请不要重复提交。

2、TokenSessionStoreInterceptor:

使用TokenSessionStoreInterceptor拦截器同样能避免重复提交,TokenSessionStoreInterceptor集成自TokenInterceptor。与上面的TokenInterceptor区别在于使用TokenSessionStoreInterceptor将不会输出任何错误信息。如果token无效,请求被导向到invalid.token结果码映射的视图。

配置如下:

<interceptor-ref name="tokenSession">
<param name="excludeMethods">default</param>
</interceptor-ref>

使用struts的同步令牌避免form的重复提交的更多相关文章

  1. 学习Java 采取令牌的方式避免重复提交

    重复提交原因 从提交页面到成功页面的跳转一般采用视图定位,由于视图定位是在服务端跳转的,如果用户在点击提交之后再次刷新页面,会导致重复提交,数据库的数据会有重复. 采用令牌措施 1.在转账展示页面生成 ...

  2. SP避免Form重复提交的三种方案

    SP避免Form重复提交的三种方案  1) javascript ,设置一个变量,只允许提交一次.   <script language="javascript">  ...

  3. struts2令牌,防止重复提交

    struts2的令牌,可以用来防止重复提交,其原理是在提交jsp页面中,写入一个隐藏域name="token",然后在action中定义一个变量token并get.set.在服务器 ...

  4. Struts(十四):通用标签-form表单

    form标签是struts2标签中一个重要标签: 可以生成html标签,使用起来和html的form标签差不多: Strut2的form标签会生成一个table,进行自动布局: 可以对表单提交的值进行 ...

  5. 防止刷新/后退引起的重复提交问题的Java Token代码,非Struts

    贴子转自http://hi.baidu.com/bobylou,转之前并没有验证文章里的方法是不是有效,估计原作者把它放到blog之前应该做过测试了吧. Struts本身有一套完善的防止重复提交表单的 ...

  6. 使用Struts 2防止表单重复提交

    用户重复提交表单在某些场合将会造成非常严重的后果.例如,在使用信用卡进行在线支付的时候,如果服务器的响应速度太慢,用户有可能会多次点击提交按钮,而这可能导致那张信用卡上的金额被消费了多次.因此,重复提 ...

  7. js阻止form表单重复提交

    防止表单重复提交的方法总体来说有两种,一种是在js中阻止重复提交:另一种是在后台利用token令牌实现,大致思路是生成一个随机码放到session和form表单的隐藏输入框中,提交表单时两者对比,表单 ...

  8. struts2视频学习笔记 29-30(Struts 2常用标签,防止表单重复提交)

    课时28 Struts 2常用标签解说 property标签 property标签用于输出指定值: <s:set name="name" value="'kk'&q ...

  9. ASP.NET Web Form和MVC中防止F5刷新引起的重复提交问题

    转载 http://www.cnblogs.com/hiteddy/archive/2012/03/29/Prevent_Resubmit_When_Refresh_Reload_In_ASP_NET ...

随机推荐

  1. MongoDB安装,启动,注册为windows系统服务

    MongoDB安装与启动 周建旭 2014-08-10 解压完后配置环境变量 下载Windows 32-bit或64-bit版本并解压缩,程序文件都在bin目录中,其它两个目录分别是C++调用是的头文 ...

  2. python学习笔记29(python中堆的使用)

    堆(heap):优先队列的一种,使用优先队列能够以任意顺序增加对象,并且能在任意时间(可能在增加对象的同时)找到(也可能是移除)最小元素,比用于列表中min的方法要高效. Python中并没有独立的堆 ...

  3. hdu 4712 Hamming Distance(随机函数暴力)

    http://acm.hdu.edu.cn/showproblem.php?pid=4712 Hamming Distance Time Limit: 6000/3000 MS (Java/Other ...

  4. Eat the Trees hdu 1693

    Problem DescriptionMost of us know that in the game called DotA(Defense of the Ancient), Pudge is a ...

  5. zoj 3620 Escape Time II dfs

    题目链接: 题目 Escape Time II Time Limit: 20 Sec Memory Limit: 256 MB 问题描述 There is a fire in LTR ' s home ...

  6. CSS+DIV:父DIV相对定位+子DIV绝对定位

    如何在一个div内将一个div进行绝对定位呢?很简单,把父div的position属性设为relative,子div的position属性设为absolute就可以了... 示例: <html& ...

  7. 关闭MyEclipse的Quick Update

    关闭MyEclipse的Quick Update, Windows > Preferences > MyEclipse > Community Essentials, 把选项 &qu ...

  8. 【leetcode】Permutations II (middle)

    Given a collection of numbers that might contain duplicates, return all possible unique permutations ...

  9. HDU4627+LCM

    思路是想到了一些 不过愣是没敢写........... /* 题意:给定一个整数n(2 <= n <= 109),满足a+b=n并且[a,b]的最小公倍数最大. */ #include&l ...

  10. linux mysql添加用户

    格式:grant select on 数据库.* to 用户名@登录主机 identified by "密码" 例1.增加一个用户user_1密码为123,让他可以在任何主机上登录 ...