1) 通过重定向
2) 通过Session Token(Session令牌):当客户端请求页面时,服务器会通过token标签生成一个随机数,并且将该随机数放置到session当中,然后将该随机数发向客户端;如果客户第一次提交,那么会将该随机数发往服务器端,服务器会接收到该随机数并且与session中所保存的随机数进行比较,这时两者的值是相同的,服务器认为是第一次提交,并且将更新服务器端的这个随机数值;如果此时再次重复提交,那么客户端发向服务器端的随机数还是之前的那个,而服务器端的随机数则已经发生了变化,两者不同,服务器就认为这是重复提交,进而转向invalid.token所指向的结果页面。
当用Session Token的时候是要配置的,且此时必须要用struts的标签库,这是他的标签库的一个增强的功能.必须在表单中加上<s:token>标签,此标签会产生两个隐藏域,
表单代码如下:
<s:form action="token.action" theme="simple">
username:<s:textfield name="username" size="20"></s:textfield><br/>
password:<s:textfield name="password" size="20"></s:textfield><br/>
<s:token></s:token>
<s:submit value="submit"></s:submit>
</s:form>
产生的隐藏域如下:
<input type="hidden" name="struts.token.name" value="struts.token" />
<input type="hidden" name="struts.token" value="AJRM7ARY2CE1CBRP9SJSTNXO58OBJVW9" />
在struts.xml中配置的invalid.token是struts提供的.
<action name="token" class="cn.wenping.struts2.TokenAction">
<result name="success">/tokenSuccess.jsp</result>
<result name="invalid.token">/tokenFail.jsp</result>
<!--
<interceptor-ref name="token"/>
<interceptor-ref name="defaultStack"/>
-->
</action>
查看<s:token>标签的处理类:叫TokenTag,一直跟到Token类里面有个tokenName = TokenHelper.DEFAULT_TOKEN_NAME;再跟到TokenHelper类里面去,TokenHelper这个类就是主要的一个处理那个标签的类.他产生一个随机数,并把这个随机数保存在session里面,再发送一份给客户端.
String token = generateGUID();就是这个方法产生的随机数,GUID是全局唯一标识符.
public static String setToken(String tokenName) {
Map session = ActionContext.getContext().getSession();
String token = generateGUID();
try {
session.put(tokenName, token);//将令牌信息放到session中去
}
catch(IllegalStateException e) {
// WW-1182 explain to user what the problem is
String msg = "Error creating HttpSession due response is commited to client. You can use the CreateSessionInterceptor or create the HttpSession from your action before the result is rendered to the client: " + e.getMessage();
LOG.error(msg, e);
throw new IllegalArgumentException(msg);
}
return token;
}
这个原理要弄清楚.理解这点就要想清楚操作到底有没有跟服务器端打交道.如后退操作是不会跟服务端打交道的.