struts2的token遏止表单重复提交(原创)

struts2的token阻止表单重复提交(原创)

最近完成了阻止struts2重复提交的功能

1.作用:经常的一个表单提交需要一定时间,在等待时间内,服务器正在处理请求,而用户可能会不断点击提交按钮,造成一个订单面的重复提交

2.如何模拟重复提交:一个表单,点击提交按钮后,刷新,会提示:(见附件)

也就是再次提交当前页面。

3.使用技术:struts2token标签

简介:jsp页面读取到<s:token/> 标签时,会在session中设置一个struts.token值,同时将此值在.jsp页面翻译做:(表单中增加两个隐藏字段,struts.token值随机生成)

如我们jsp页面写<s:token name=”mytoken”/>

那么翻译做:

<input type="hidden" value=" mytoken " name="struts.token.name">

<input type="hidden" value="FKZCDK5XC881W05MLVK0JQJP04M0KZC2" name=" mytoken ">

如果写作<s:token/>

则翻译做:

<input type="hidden" value="struts.token" name="struts.token.name">

<input type="hidden" value="FKZCDK5XC881W05MLVK0JQJP04M0KZC2" name="struts.token">

接着~

提交表单到我们指定的Action时先会先经过token拦截器, token拦截器会从form表单中获取token值, 再从session中获取token(注:我们可以在action中设置mytoken属性,String类型的,加getset方法,提交表单的时候就会像表单其他属性一样set值进去,取值出来;同时,我们可以取得httpsession,从里面getAttribute(“mytoken”)出来) 比较两个值是否相同 不相同, 直接返回 invalid.tokeninvalid.token应配置成重复提交表单的提示信息页面)相同,removesession里的 struts.token(防止被重复使用), 继续正常流程

例如,我们进入a.jsp,那么里面就默认有token的隐藏域了,session里也有token值了。我们第一次点击提交,在进入action之前会进去到token拦截器里,token取出页面和session里的token比对,相同的则提交表单。不同的,根据我们设置,比如返回页面,显示提示信息(<s: actionerror/>),跳到错误页面,进入等待页面等。这个看我们struts.xml的配置了。

说一句:无论那种处理,使用struts2token来阻止重复提交修改的就俩地:

一、form表单加<s:token/>(如果是错误信息显示<s: actionerror/>

二、配置文件struts.xml(配置拦截器,配置跳转页面,等待页面)

注:写上一后,session和页面就有token值了。我们在struts2action中可以取到这两处的值~

但是,拦截器不会起作用,也就是说不会阻止表单提交

 

 

本人遇到的不解是:

1、页面解析到<s:token/>时候会将此token放到session中,同时在页面解析做两个hidden。

2、相同的则会提交表单,并移除session里的token(真的吗?),不同则会视为重复提交,阻止提交

 

 

使用firebug发现:第一次提交表单,session里的token和表单里的一样,刷新之后,session里的token变了(但是不是空的),而表单里的值和先前一样没有变(这个和上面说的有悖)

 

 

有个点需要注意:

两个token一样表单才可提交;不一样就视为重复提交了,会被阻止

本人使用的是,如果重复提交,弹出对话框,并终止程序进入action

1.页面

<body onload="show(<s:property value='repeat'/>)">

<form>

<s:token name="mytoken"/>

</form>

</body>

js:if(){alert("stop!repeat");}

2.action  

private String mytoken;(get/set)

private boolean repeat;(get/set)

public void validate() {
  String tokenInSession = (String) httpSession.getAttribute("token");
  if (StringUtils.isNotEmpty(mytoken)
    && StringUtils.isNotEmpty(tokenInSession)) {
   if (!tokenInSession.equals(token)) {
    // no
    repeatFlag = true;
    addFieldError("repeatMsg", "repeat");//这句话没有显示,单纯的告诉calidate验证不通过别执行下面的action了
   }
  }
 }

struts.xml中配置没有改变只是多一个

<result name="input">/view/goods_apply.jsp</result>

注:name="input"在什么时候用呢?

答:在validate验证错误的时候会跳到这个页面~

 

 

 

 

上面写的更多的是我自己总结出来方法和原理,有不对的地方希望大家多指教。想具体学习,可以网搜(struts2阻止重复提交)会有很多很全面的文章

祝大家学习愉快~~~