`
jessen163
  • 浏览: 465420 次
  • 性别: Icon_minigender_1
  • 来自: 潘多拉
社区版块
存档分类
最新评论

解决struts1.x表单重复提交问题

阅读更多
每次填写完表单后单击提交后,struts中action执行相关业务逻辑,通过forward对象转到某个页面。这时若刷新页面后,会再执行同样的逻辑。比如录数据到数据库,按照上面的情况,数据库中会有两条同样的数据。为了避免这种情况,有几种解决办法:

1 :在执行业务逻辑后,返回一个Forward对象,这个forward对象的path属性应该配置一个幂等的XXX.do操作,这样可以解决,但是有可能不符合用户的要求,所以还有其他方法。

2:重定向,在配置文件里配置redirect属性<forward redirect="true" path="/xxx/xxx.jsp">,重定向到xxx.jsp。这种情况下会丢失request范围内的参数,若xxx.jsp不要求这些参数就可以,如操作的数据保存在session范围内,就不会影响整体效果。但还是有弊端。

3:利用struts1.x令牌能很好解决这类问题。

必要条件:在表单内,必须使用struts的库标签如:<html:form>。


如下例子:

LoginAction:
 package com.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  {
    public ActionForward get(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
           throws Exception  {
       //保存令牌(保存在jsp动态生成的32位jsessionid)\
        this.saveToken(request);
        System.out.println("begin save");
        return mapping.findForward("login");
    }
    
    public ActionForward login(ActionMapping mapping, ActionForm form,
            HttpServletRequest request, HttpServletResponse response)
            throws Exception  {
        /**//*if(this.isTokenValid(request))
        {
            System.out.println("valid");
            this.resetToken(request);
            return mapping.findForward("ok");
        }*/
        //这个写法和上面注释部分一样效果
        if(this.isTokenValid(request,true))
         {
            System.out.println("valid");
            return mapping.findForward("ok");
        }
        else
        {
            System.out.println("invalid");
            return mapping.findForward("error");
        }
    }
}

struts-config.xml:
<?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">
 <struts-config>
     <data-sources />
     <form-beans>
         <form-bean name="loginForm" type="com.web.form.LoginForm"></form-bean>
     </form-beans>
     <global-exceptions />
     <global-forwards />
     <action-mappings>
         <action path="/login" parameter="method" name="loginForm"
             type="com.web.action.LoginAction">
             <forward name="login" path="/login.jsp" />
             <forward name="ok" path="/ok.jsp" />
             <forward name="error" path="/error.jsp" />
         </action>
     </action-mappings>
     <message-resources parameter="" />
 </struts-config>

index.jsp:
<% @page contentType="text/html; charset=GBK"%>
<% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
 <c:set var="ctx" value="${pageContext.request.contextPath}" />
 <html>
   <head>
     <title>My Jsp</title>
   </head>
   <body>
   <a href="${ctx}/login.do?method=get">发言</a>
   </body>
 </html>



login.jsp:
<% @page contentType="text/html; charset=GBK"%>
<% @taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<% @taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html" %>
 <html>
   <head>
     <title>My Jsp</title>
   </head>
   <body>
   <c:set var="ctx" value="${pageContext.request.contextPath}"/>
   <!-- 此处必须使用html标签,否则token不能用 -->
   <html:form action="login.do?method=login" method="post">
     <html:submit value="提交"></html:submit>
   </html:form>
   </body>
 </html>

当你运行第一次的时候,会提示你"成功".
这时我们退到login.jsp查看一下源代码:
<html>
   <head>
     <title>My Jsp</title>
   </head>
   <body>
   
   <form name="loginForm" method="post" action="/strutsToken/login.do?method=login">
 <div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="d7484f95247cf242a6f35107a1c7ac25"></div>
     <input type="submit" value="提交">
   </form>
   </body>
 </html>


对比一下我们写的login.jsp多了一个隐藏域:
<div><input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="d7484f95247cf242a6f35107a1c7ac25"></div>
此时生成了一个32位的唯一的JsessionID做为值.
与LoginAction中的get方法的saveToken(request)是一样的.
此句的作用就是把一个jsessionid保存到request范围里.

在我们后退重新调用:
if(this.isTokenValid(request,true))
         {
            System.out.println("valid");
            return mapping.findForward("ok");
        }
时,就会拿login.jsp里传过来的jsessionid和request的
进行比较,如果一样,说明不合法.因为我们的操作都是在一个请求会话里
操作的.说明你在重复提交.
如果不一样,说明重新生成了一个唯一的jsessionid(新开一个浏览器),
开启了一个新会话,重新提交,这是合法的.
这样就防止了表单重复提交问题.
为了防止表单重复提交,一般在设计action方法时:如录入数据,设计成两个方法,add()和insert(),在add方法中保存令牌并转到页面,在页面提交到insert方法中,判断令牌。


分享到:
评论

相关推荐

    Struts1.x实现防止提交的Token使用示例

    通过以上步骤,Struts1.x的Token机制就能有效地防止重复提交和CSRF攻击。在实际项目中,可以根据具体需求进行适当的调整,例如增加对Ajax请求的支持,或者自定义错误处理逻辑。记住,安全是Web开发中不可忽视的一...

    struts1.x 常用知识详解

    Struts1.x是Apache软件基金会开发的一个开源框架,主要用于构建基于Java的企业级Web应用程序。它在MVC(Model-View-Controller)设计模式的基础上提供了一种实现方式,使得开发者能够更方便地处理业务逻辑、视图展示...

    Struts1.x令牌(Token)的使用.rar

    为了解决这些问题,Struts1.x引入了令牌机制。 令牌的工作流程大致如下: 1. 用户打开一个表单页面,服务器在生成页面时,会在后台生成一个唯一的令牌,并将其存储到session中,同时将令牌值隐藏在表单中。 2. ...

    struts1.x_Tags

    - `&lt;redirect&gt;`: 实现URL重定向,通常用于跳转到外部资源或者防止表单重复提交。 - `&lt;include&gt;`: 用于在页面中嵌入其他页面或资源,提供动态包含的功能。 2. **HTML标签库(HTML Tags)**: - `&lt;html:form&gt;`: 创建...

    Struts 1.x中批量封装对象

    Struts 1.x 是一个非常经典的Java Web框架,它在早期的Web开发中占据了重要的地位。这个框架的主要目的是为了提供一种MVC(Model-View-Controller)架构,以帮助开发者更好地组织和管理Web应用程序的逻辑。批量封装...

    Struts2入门教程(全新完整版)

    5. TokenInterceptor防止表单重复提交。 34 6.使用拦截器实现权限验证 35 7.拦截器中的注解 37 8.使用PreResultListener实现回调 39 六、使用标签 40 1.基础表单标签 40 2.单选按钮和复选框: 41 3.三种方式实现下拉...

    struts2学习笔记.doc

    #### 七、表单重复提交 **7.1 问题分析** - **原因分析**:用户可能由于网络延迟等原因导致多次点击提交按钮,造成数据重复。 - **解决方案**: - 使用Token机制防止重复提交。 - 在`struts.xml`中配置Token拦截器...

    struts1.3.10

    ActionForm对象在请求之间可以进行回话持久化,以支持表单的重复提交。 3. **Action**:这是处理业务逻辑的类,它接收ActionForm对象并执行必要的操作。Action类通过调用服务层方法完成业务处理,然后返回一个表示...

    Struts动态表单验证

    Validator框架则是Struts 1.x中的增强功能,允许更灵活的XML配置和可重用的验证规则。 4. **Validator框架** - **ValidatorConfig**:配置文件(如struts-validator.xml或struts-config.xml)定义了验证规则和错误...

    struts1.3页面跳转问题

    对于需要改变URL或者避免用户重复提交的情况,我们会选择重定向。在Action类中,可以使用`ActionRedirect`或`RedirectAction`类(Struts1.3.x后期版本)来实现: ```java ActionRedirect redirect = new ...

    张孝祥09年struts高级实战进阶PPT

    - **防止表单重复提交**:为了避免用户误操作导致的多次请求,可以通过令牌机制或JavaScript禁用提交按钮来防止重复提交。 **5. 用户界面组件** - **复选框的使用技巧**:在Struts中处理复选框的数据通常需要使用...

    struts框架、及其标签使用的一些相关文档

    在实际应用中,Struts还提供了一种防止重复提交的机制,这在`Struts令牌防止重复提交.docx`中有所阐述。通过在请求中添加令牌,服务器可以在接收到请求时检查该令牌,如果发现重复的令牌,则拒绝处理,从而避免了因...

    简单的struts教程

    1. **下载Struts 2**:根据教程中的提示,建议下载Struts 2.1.x版本。 2. **安装Eclipse for Java EE**:这是一款强大的IDE,适合Java Web开发。教程中提到了需要下载Eclipse for Java EE,这是为了方便进行Struts 2...

    JAVA WEB典型模块与项目实战大全

    5.5 避免重复提交功能  5.6 缩略加水印图像  5.7 小结  第6章 网络硬盘  6.1 网络硬盘功能原理  6.2 网络硬盘功能具体实现——浏览磁盘和显示文件信息  6.3 网络硬盘功能具体实现——操作文件夹和文件...

    Struts2.1学习笔记

    - **token防止表单重复提交**:使用`&lt;s:token&gt;`标签可以生成一个隐藏字段,防止用户多次提交同一个表单。 通过以上内容的学习,可以全面了解Struts2.1框架的核心特性和使用方法,这对于开发者来说是非常宝贵的资源...

    struts1.2下实现文件上传进度条

    - 在`resources/js/upload.js`文件中添加代码,禁用表单提交按钮,防止用户重复提交。 ```javascript function disableSubmit() { var allInputs = document.forms[0].getElementsByTagName('input'); for (var...

    Struts2+Spring+Hibernate知识点总结

    综上所述,Struts2、Spring和Hibernate是Java Web开发中常用的三大框架,它们各自解决了不同层面的问题。Struts2负责处理Web请求,Spring则关注于业务逻辑的组织和管理,而Hibernate专注于对象和数据库之间的映射。...

    java_学习资料

    - **目的**:防止表单重复提交。 - **实现**:通过在表单中添加一个隐藏字段,并在提交表单前验证该字段的值是否有效。 **文件上传** - **原理**:使用MultipartRequest来处理含有文件的HTTP请求。 - **实现**:...

Global site tag (gtag.js) - Google Analytics