每次填写完表单后单击提交后,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机制就能有效地防止重复提交和CSRF攻击。在实际项目中,可以根据具体需求进行适当的调整,例如增加对Ajax请求的支持,或者自定义错误处理逻辑。记住,安全是Web开发中不可忽视的一...
Struts1.x是Apache软件基金会开发的一个开源框架,主要用于构建基于Java的企业级Web应用程序。它在MVC(Model-View-Controller)设计模式的基础上提供了一种实现方式,使得开发者能够更方便地处理业务逻辑、视图展示...
为了解决这些问题,Struts1.x引入了令牌机制。 令牌的工作流程大致如下: 1. 用户打开一个表单页面,服务器在生成页面时,会在后台生成一个唯一的令牌,并将其存储到session中,同时将令牌值隐藏在表单中。 2. ...
- `<redirect>`: 实现URL重定向,通常用于跳转到外部资源或者防止表单重复提交。 - `<include>`: 用于在页面中嵌入其他页面或资源,提供动态包含的功能。 2. **HTML标签库(HTML Tags)**: - `<html:form>`: 创建...
Struts 1.x 是一个非常经典的Java Web框架,它在早期的Web开发中占据了重要的地位。这个框架的主要目的是为了提供一种MVC(Model-View-Controller)架构,以帮助开发者更好地组织和管理Web应用程序的逻辑。批量封装...
5. TokenInterceptor防止表单重复提交。 34 6.使用拦截器实现权限验证 35 7.拦截器中的注解 37 8.使用PreResultListener实现回调 39 六、使用标签 40 1.基础表单标签 40 2.单选按钮和复选框: 41 3.三种方式实现下拉...
#### 七、表单重复提交 **7.1 问题分析** - **原因分析**:用户可能由于网络延迟等原因导致多次点击提交按钮,造成数据重复。 - **解决方案**: - 使用Token机制防止重复提交。 - 在`struts.xml`中配置Token拦截器...
ActionForm对象在请求之间可以进行回话持久化,以支持表单的重复提交。 3. **Action**:这是处理业务逻辑的类,它接收ActionForm对象并执行必要的操作。Action类通过调用服务层方法完成业务处理,然后返回一个表示...
Validator框架则是Struts 1.x中的增强功能,允许更灵活的XML配置和可重用的验证规则。 4. **Validator框架** - **ValidatorConfig**:配置文件(如struts-validator.xml或struts-config.xml)定义了验证规则和错误...
对于需要改变URL或者避免用户重复提交的情况,我们会选择重定向。在Action类中,可以使用`ActionRedirect`或`RedirectAction`类(Struts1.3.x后期版本)来实现: ```java ActionRedirect redirect = new ...
- **防止表单重复提交**:为了避免用户误操作导致的多次请求,可以通过令牌机制或JavaScript禁用提交按钮来防止重复提交。 **5. 用户界面组件** - **复选框的使用技巧**:在Struts中处理复选框的数据通常需要使用...
在实际应用中,Struts还提供了一种防止重复提交的机制,这在`Struts令牌防止重复提交.docx`中有所阐述。通过在请求中添加令牌,服务器可以在接收到请求时检查该令牌,如果发现重复的令牌,则拒绝处理,从而避免了因...
1. **下载Struts 2**:根据教程中的提示,建议下载Struts 2.1.x版本。 2. **安装Eclipse for Java EE**:这是一款强大的IDE,适合Java Web开发。教程中提到了需要下载Eclipse for Java EE,这是为了方便进行Struts 2...
5.5 避免重复提交功能 5.6 缩略加水印图像 5.7 小结 第6章 网络硬盘 6.1 网络硬盘功能原理 6.2 网络硬盘功能具体实现——浏览磁盘和显示文件信息 6.3 网络硬盘功能具体实现——操作文件夹和文件...
- **token防止表单重复提交**:使用`<s:token>`标签可以生成一个隐藏字段,防止用户多次提交同一个表单。 通过以上内容的学习,可以全面了解Struts2.1框架的核心特性和使用方法,这对于开发者来说是非常宝贵的资源...
- 在`resources/js/upload.js`文件中添加代码,禁用表单提交按钮,防止用户重复提交。 ```javascript function disableSubmit() { var allInputs = document.forms[0].getElementsByTagName('input'); for (var...
综上所述,Struts2、Spring和Hibernate是Java Web开发中常用的三大框架,它们各自解决了不同层面的问题。Struts2负责处理Web请求,Spring则关注于业务逻辑的组织和管理,而Hibernate专注于对象和数据库之间的映射。...
- **目的**:防止表单重复提交。 - **实现**:通过在表单中添加一个隐藏字段,并在提交表单前验证该字段的值是否有效。 **文件上传** - **原理**:使用MultipartRequest来处理含有文件的HTTP请求。 - **实现**:...
`<s:token>` 生成和检查令牌,防止重复提交。 Y. `<s:url>` 创建URL,可以附加参数,例如:`<s:url action="myAction"><s:param name="param1" value="value1" /></s:url>`。 Z. `<s:validate>` 验证表单字段。 ...