(1)
在用户进入表单页面的时候生成一个随机的数字,并赋值给一个session,并写入一个隐藏控件
在处理提交数据的页面判断传入的隐藏控件的值是否=session的值。
相等表明允许提交
最重要的一步:处理提交的数据成功后清空session,这样他反复提交过来的页面,隐藏控件的值是存在的,而session为空,就backup页面,告诉他,不能提交了
(2)
用Struts的Token机制解决表单重复提交
2006年09月11日 星期一 上午 09:23
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); } } |
分享到:
相关推荐
综上所述,Struts2框架提供了token机制以及灵活的跳转方式配置来解决表单重复提交的问题。开发者在使用时需要注意配置token相关标签和拦截器,并通过设置正确的结果视图跳转类型来防止因刷新页面导致的重复提交。...
要彻底解决表单重复提交的问题,有以下几种策略: - **禁用表单按钮**:在表单提交后,禁用提交按钮,防止用户点击多次。 - **使用POST/REDIRECT/GET模式**:在处理POST请求后,使用`sendRedirect()`重定向到一个新...
本文将详细阐述两种客户端限制表单重复提交的方法,并结合Struts框架的Token机制进行深入理解。 ### 第一种方法:JavaScript设置标志变量 这种方法通过在JavaScript中定义一个标志变量`repeatSubmitFlag`来判断...
表单重复提交问题主要是因为Web请求的工作方式。每次用户刷新页面时,如果表单已经提交过,则该表单会再次被提交。这对于某些应用场景来说是不可接受的,比如支付系统、订单系统等。因此,如何有效地避免表单的重复...
在服务器端,我们可以通过两种主要方式来处理: session 和 token 。session可以记录用户是否已经提交过数据,如果检测到已提交,则拒绝再次提交。例如,在PHP中: ```php session_start(); if (!isset($_SESSION['...
通过上述介绍可以看出,Struts的Token机制提供了一种简单而有效的解决方案来避免表单重复提交的问题。开发者只需要遵循一定的编码规范和逻辑结构,就可以轻松地在自己的项目中实现这一机制。这对于提高Web应用的数据...
几种防止表单重复提交的方法 禁掉提交按钮。表单提交后使用Javascript使提交按钮disable。这种方法防止心急的用户多次点击按钮。但有个问题,如果客户端把Javascript给禁止掉,这种方法就无效了。 我之前的文章曾说...
在IT领域,尤其是在Web开发中,表单重复提交是一个常见的问题,可能导致数据不一致或数据库冗余。本文将深入探讨如何在客户端和服务器端通过不同的方法来防止这种情况发生。 首先,客户端的防护主要依赖于...
防止表单重复提交的方法通常有两种:客户端解决方案和服务器端解决方案。 1. 客户端解决方案: - JavaScript禁用提交按钮:在提交表单时,可以通过JavaScript立即禁用提交按钮,避免用户连续点击。 - 使用Ajax...
在Web开发中,表单重复提交是一个常见的问题,可能导致数据不一致或处理逻辑的混乱。Struts2提供了多种方法来防止这种情况,其中一种是通过重定向来实现。下面将详细解释Struts2如何通过重定向来防止表单重复提交。 ...
Token机制是一种常用的防止表单重复提交的技术方案。其基本思想是在用户提交表单时,服务器会生成一个唯一的Token并将其存储在客户端(如通过Cookie或隐藏字段),同时也会在服务器端存储一份。当用户提交表单时,...
"禁止表单重复提交"和"网页加载的等待效果"是两个关键的优化点,旨在提高用户满意度和减少不必要的数据处理。 首先,让我们详细讨论如何禁止表单重复提交。在网页中,用户可能会意外地多次点击提交按钮,导致服务器...
对于后面两种情况,可以使用Session防止表单重复提交。方法是,在运行添加信息页面时,在Session中放置信息,然后页面提交信息给Servlet处理,Servlet获取Session中的信息,如果Session中有信息不为空则将信息插入...
解决重复提交问题的8种方案 在本篇文章中,我们将讨论重复提交问题的八种解决方案。重复提交问题是指在Web应用程序中,当用户提交表单时,可能会导致重复提交,导致数据不一致和其他问题。为了解决这个问题,我们...
此外,服务器端的事务管理也是防止重复提交的一种方式。在数据库操作中使用事务,确保一系列操作要么全部成功,要么全部失败。这样即使有重复提交,也只会执行一次有效操作。 还可以考虑使用AJAX异步提交,通过...
总的来说,Struts2的Token机制是一种有效防止表单重复提交的方法,它通过生成和验证唯一标识来确保每个请求的唯一性,从而保护了业务的正确性和数据的一致性。在实际开发中,根据项目需求和安全策略,我们可以灵活...
重复提交通常由两种情况引起: 1. 服务器处理时间过长,用户可能在未收到响应时多次点击提交按钮。 2. 使用`forward`方式跳转,导致用户刷新页面时再次提交数据。为了避免这种情况,可以选择使用`redirect`,但某些...
第一种:用flag标识,下面的代码设置... //当表单被提交过一次后checkSubmitFlg将变为true,根据判断将无法进行提交。 } checkSubmitFlg ==true; return true; } < /script > < form name=”form1” method=”pos