token防重复提价

       如果网络不好,提交数据后可能就没有反应了。这时候用户不知道数据是否已提交到服务器了,往往还会单击提交按钮再提交一次。对于某些应用,例如网络购物,银行转账等,重复提交会导致非常严重的后果。

解决这个问题可以采用箭牌令(token) 原理是这样的: 客户请求某个页面时如A.jsp。 web服务器在服务端和客户端同时都放了一个箭牌令,这两个值是相同的。当A.jsp提交时 将A.jsp中所带的箭牌令和服务端的箭牌令相比较。如果相同则表示是第一次提交,在返回前修改服务端的箭牌令德值。当A.jsp由于刷新,或其他原因再次提交时,在服务端任就将A.jsp带的箭牌令与服务端的箭牌令比较,这时由于服务端的箭牌令已被修改。所以两者值不同。因此可以判断是重复提交。

 

看看struts1如何处理

用户请求录入页面,这个与服务器建立的一次连接过程中,
在服务器端①【生成一个session标识,同时返回到客户端一个与此匹配的hidden域】。
用户提交了此页面,服务器端首先②【判断此hidden域与session标识是否匹配】,
若不匹配,终止保存操作,提示同一表单不能提交两次,
同时①【新建一个session标识和hidden域】,返回录入页面;
若匹配,执行插入保存操作,同时③【清空(重置reset)session标识】。
Struts正在基于这样的思路在org.apache.struts.action.Action类中提供了内置支持方法:
protected void saveToken(HttpServletRequest request) 配合标签对应于①
protected boolean isTokenValid(HttpServletRequest request) 对应于②
protected void resetToken(HttpServletRequest request) 对应于③
注意:
1.token.jsp必须用html:form标签

记住一点,Struts在你每次访问Action的时候,都会产生一个令牌,保存在你的Session里面,如果你在Action里的函数里面,使用了saveToken(request);,那么这个令牌也会保存在这个Action所Forward到的jsp所生成的静态页面里。
如果你在你Action的方法里使用了isTokenValid,那么Struts会将你从你的request里面去获取这个令牌值,然后和Session里的令牌值做比较,如果两者相等,就不是重复提交,如果不相等,就是重复提交了。

当然你也可以在你的action所继承的父类里面做表单重复提交的控制,这样就可以不用在所有的子类里来分别再写防止重复提交的代码

index.jsp

Java代码 复制代码
  1. <%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>   
  2. <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>   
  3. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">   
  4. <html>   
  5.   <head>   
  6.     <title>My JSP 'index.jsp' starting page</title>   
  7. </head>   
  8.      
  9.   <body>   
  10.     <html:link action="token.do?method=token">Token</html:link>   
  11.   </body>   
  12. </html>   
  13.   
  14. TokenAction.java  
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My JSP 'index.jsp' starting page</title>
</head>
  
  <body>
    <html:link action="token.do?method=token">Token</html:link>
  </body>
</html>

TokenAction.java


Java代码 复制代码
  1. public class TokenAction extends DispatchAction {   
  2.        
  3.     public ActionForward token(ActionMapping mapping, ActionForm form,   
  4.             HttpServletRequest request, HttpServletResponse response) {   
  5.         TokenForm tokenForm = (TokenForm) form;   
  6.         //saveToken创建一个新令牌,如果没有调用此方法,那么页面不会生成隐藏标签   
  7.         this.saveToken(request);   
  8.         return mapping.findForward("token");   
  9.     }   
  10.        
  11.     public ActionForward add(ActionMapping mapping, ActionForm form,   
  12.             HttpServletRequest request, HttpServletResponse response) {   
  13.         TokenForm tokenForm = (TokenForm) form;   
  14.         //如果为假,则进行了重复提交    
  15.         if(isTokenValid(request,true)){   
  16.             System.out.println("正常提交");   
  17.             this.resetToken(request);   
  18.         }else{   
  19.             System.out.println("重复提交");   
  20.             //重新生成令牌   
  21.             this.saveToken(request);   
  22.             return mapping.getInputForward();   
  23.         }   
  24.         return mapping.findForward("token");   
  25.     }   
  26. }  
public class TokenAction extends DispatchAction {
	
	public ActionForward token(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		TokenForm tokenForm = (TokenForm) form;
		//saveToken创建一个新令牌,如果没有调用此方法,那么页面不会生成隐藏标签
		this.saveToken(request);
		return mapping.findForward("token");
	}
	
	public ActionForward add(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response) {
		TokenForm tokenForm = (TokenForm) form;
		//如果为假,则进行了重复提交 
		if(isTokenValid(request,true)){
			System.out.println("正常提交");
			this.resetToken(request);
		}else{
			System.out.println("重复提交");
			//重新生成令牌
			this.saveToken(request);
			return mapping.getInputForward();
		}
		return mapping.findForward("token");
	}
}



token.jsp

Java代码 复制代码
  1. <%@ page language="java" pageEncoding="UTF-8"%>   
  2. <%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%>    
  3. <%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>   
  4.     
  5. <html>    
  6.     <head>   
  7.         <title>JSP for TokenForm form</title>   
  8.     </head>   
  9.     <body>   
  10.         <html:form action="/token.do?method=add">   
  11.             查看源代码可以看到隐藏标签,隐藏域value值的"32位随机码<br>   
  12.             姓名: <html:password property="username"/><br/>   
  13.             密码 : <html:text property="password"/><br/>   
  14.             <html:submit/><html:cancel/>   
  15.         </html:form>   
  16.     </body>   
  17. </html>  
<%@ page language="java" pageEncoding="UTF-8"%>
<%@ taglib uri="http://jakarta.apache.org/struts/tags-bean" prefix="bean"%> 
<%@ taglib uri="http://jakarta.apache.org/struts/tags-html" prefix="html"%>
 
<html> 
	<head>
		<title>JSP for TokenForm form</title>
	</head>
	<body>
		<html:form action="/token.do?method=add">
			查看源代码可以看到隐藏标签,隐藏域value值的"32位随机码<br>
			姓名: <html:password property="username"/><br/>
			密码 : <html:text property="password"/><br/>
			<html:submit/><html:cancel/>
		</html:form>
	</body>
</html>



struts-config.xml

Java代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>   
  2. <!DOCTYPE struts-config PUBLIC "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN" "http://struts.apache.org/dtds/struts-config_1_2.dtd">   
  3.   
  4. <struts-config>   
  5.   <data-sources />   
  6.   <form-beans >   
  7.     <form-bean name="tokenForm" type="com.dahai.struts.form.TokenForm" />   
  8.   
  9.   </form-beans>   
  10.   
  11.   <global-exceptions />   
  12.   <global-forwards />   
  13.   <action-mappings >   
  14.     <action   
  15.       attribute="tokenForm"  
  16.       input="/token.jsp"  
  17.       name="tokenForm"  
  18.       parameter="method"  
  19.       path="/token"  
  20.       scope="request"  
  21.       type="com.dahai.struts.action.TokenAction" >   
  22.       <forward name="token" path="/token.jsp"/>   
  23.       </action>   
  24.   </action-mappings>   
  25.   
  26.   <message-resources parameter="com.dahai.struts.ApplicationResources" />   
  27. </struts-config>  
<?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="tokenForm" type="com.dahai.struts.form.TokenForm" />

  </form-beans>

  <global-exceptions />
  <global-forwards />
  <action-mappings >
    <action
      attribute="tokenForm"
      input="/token.jsp"
      name="tokenForm"
      parameter="method"
      path="/token"
      scope="request"
      type="com.dahai.struts.action.TokenAction" >
      <forward name="token" path="/token.jsp"/>
      </action>
  </action-mappings>

  <message-resources parameter="com.dahai.struts.ApplicationResources" />
</struts-config>


再来看看struts2如何处理

以TokenAction为例

TokenAction中有一个names属性,用来存储提交过的所有的数据。重复提交数据时,如果能提交进来,names中将会积累重复的数据,以此来判断数据是否被重复提交。

package com.helloweenvsfei.strutes.action;

public class TokenAction extends ActionSupport{

      private String name;
      public String execute(){
      names.add(name);
      return Action.SUCCESS;
      }
      
      public void setName(String name) {
        this.name = name;

      }
      public static List<String> getNames() {
            return names;

     }

}

 

struts.xml:

<struts>
 <!-- Include webwork default (from the Struts JAR). -->
 <include file="struts-default.xml"/>

 <!-- Configuration for the default package. -->
 <package name="default" extends="struts-default">
  
  <!-- Default interceptor stack. -->
  <default-interceptor-ref name="paramsPrepareParamsStack"/>
  <action name="token" class="action.TokenAction">
   <interceptor-ref name="token" /> <!-- token拦截器 -->
      <interceptor-ref name="basicStack"/>
   <result name="success">/jsp/tokenSuccess.jsp</result> 
   <result name="input">/jsp/tokenInput.jsp</result> 
   <result name="invalid.token">/jsp/tokenInvalid.jsp</result> 
  </action>  
 </package>
</struts>

 

提交页面

<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>   
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<%@ taglib uri="/struts-tags" prefix="struts" %>

<struts:form action="token">
 <struts:token /> <!-- token拦截器 -->
    <struts:label>避免重复输入</struts:label>
  <struts:textfield name="name" label="请输入姓名" />
  <struts:submit name="提交"/>
</struts:form>

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值