关于使用isTokenValid 的那个方法:
一,首先介绍一下struts 提供的有关令牌环的相关方法
请求有效性处理, 使用令牌可以有效的防止重复提交。
protected String generateToken(HttpServletRequest request) 创建一个令牌.
protected boolean isTokenValid(HttpServletRequest request) 检查令牌是否有效
protected boolean isTokenValid(HttpServletRequest request,Boolean reset) 检查令牌是否有效,并且重置令牌(如果reset 是true )
protected void resetToken(HttpServletRequest request) 重置令牌
protected void saveToken(HttpServletRequest request) 添加令牌
二,利用struts 的同步令牌机制
利用同步令牌(Token )机制来解决Web 应用中重复提交的问题,Struts 也给出了一个参考实现。
基本原理:
服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,
看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给
客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次
提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
if (isTokenValid(request, true)) {
// your code here
return mapping.findForward("success");
} else {
saveToken(request);
return mapping.findForward("submitagain");
}
Struts 根据用户会话ID 和当前系统时间来生成一个唯一(对于每个会话)令牌的,具体实现可以参考
TokenProcessor 类中的generateToken() 方法。
1. // 验证事务控制令牌,<html:form > 会自动根据session 中标识生成一个隐含input 代表令牌,防止两次提交
2. 在act ion 中:
//<input type="hidden" name="org.apache.struts.taglib.html.TOKEN"
// value="6aa35341f25184fd996c4c918255c3ae">
if (!isTokenValid(request))
errors.add(ActionErrors.GLOBAL_ERROR,
new ActionError("error.transaction.token"));
resetToken(request); // 删除session 中的令牌
3. act ion 有这样的一个方法生成令牌
protected String generateToken(HttpServletRequest request) {
HttpSession session = request.getSession();
try {
byte id[] = session.getId().getBytes();
byte now[] =
new Long(System.currentTimeMillis()).toString().getBytes();
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(id);
md.update(now);
return (toHex(md.digest()));
} catch (IllegalStateException e) {
return (null);
} catch (NoSuchAlgorithmException e) {
return (null);
}
}
声明: 提交表单时,必须使用html 标签, 否则token 不能用
但是一种方法可以解决该问题:
在页面中加入一个隐藏域
<input type="hidden"
name="org.apache.struts.taglib.html.TOKEN"
value="<%(String)session.getAttribute(
Globals.TRANSACTION_TOKEN_KEY)%>">
因为,Struts 产生的令牌Key 存放在Session 内