Struts的Token(令牌)机制能够很好的解决表单重复提交的问题,基本原理是:服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。

具体使用方法如下:

1.先在一个Action中,调用saveToken(HttpServletRequest request)方法。然后转向带有表单的JSP页面。

2.在JSP页面提交表单给一个Action,再这个Action中进行是否为重复提交的判断。

 1     if (isTokenValid(request, true)) {
2
3 // 未重复提交时,正确的时候应该做的事情
4
5 return mapping.findForward("success");
6
7 } else {
8
9 // 重复提交时,需要做的事情
10
11 saveToken(request);
12
13 return mapping.findForward("error");
14
15 }

Struts Token 机制原理:

1,  由第一个Action调用saveToken(HttpServletRequest request),这个方法内部实现如下:

protected void saveToken(HttpServletRequest request) {

        token.saveToken(request);

}

public synchronized void saveToken(HttpServletRequest request) {

        HttpSession session = request.getSession();

        String token = generateToken(request);

        if (token != null) {

            session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token);

        }

}

这个方法调用generateToken方法实现如下:

 public synchronized void saveToken(HttpServletRequest request) {

        HttpSession session = request.getSession();

        String token = generateToken(request);

        if (token != null) {

            session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token);

        }

}

generateToken完毕后,将得到的唯一值setAttribute到session中。

 session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token);

Globals.TRANSACTION_TOKEN_KEY的值是:” org.apache.struts.action.TOKEN”

然后跳转到JSP页面。

2,  JSP页面的Struts自定义标签 <html:form>的标签类:org.apache.struts.taglib.html. FormTag

这个类的doStartTag()方法会调用本类的renderToken()方法。

protected String renderToken() {

        StringBuffer results = new StringBuffer();

        HttpSession session = pageContext.getSession();

        if (session != null) {

            String token =

                (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);

            if (token != null) {

                results.append("<input type=\"hidden\" name=\"");

                results.append(Constants.TOKEN_KEY);

                results.append("\" value=\"");

                results.append(token);

                if (this.isXhtml()) {

                    results.append("\" />");

                } else {

                    results.append("\">");

                }

            }

        }

        return results.toString();

}

这样子会生成类似于

 <input type="hidden" name="org.apache.struts.taglib.html.TOKEN"
value="6aa35341f25184fd996c4c918255c3ae">

的隐藏标签。

然后提交到一个Action中,在Action中用isTokenValid()方法进行比较session中” org.apache.struts.action.TOKEN”的这个key所对应的值和提交来的request中的” org.apache.struts.action.TOKEN”的这个value是否一致。

如果为true,那么证明可以提交。如果为false,证明已经重复,不允许提交。

最新文章

  1. 函数调用方式__stdcall、__cdel
  2. C++中默认构造函数中数据成员的初始化
  3. 自定义android程序一段时间无操作后的功能
  4. Windows API学习---用户方式中的线程同步
  5. HTML5,CSS3 与 Javascript 制作视频播放器
  6. 使用slice和concat对数组的深拷贝和浅拷贝
  7. Hadoop学习笔记五
  8. SharePoint Javascript客户端应用入门
  9. jQuery源码——.html()方法原理解析
  10. meterpreter 渗透用法
  11. 前端页面调用Spring boot接口发生的跨域问题
  12. 简单的策略模式Strategy演示
  13. 反射入门-浅谈反射用途_根据Ado游标对象创建list集合
  14. 您还在用下一步下一步的方式安装SQLSERVER和SQLSERVER补丁吗?
  15. Android Studio 之 导入Eclipse项目常见问题及解决方案
  16. cropper图片剪裁 , .toBlob()报错
  17. SQL触发器与CLR的使用
  18. 23 DesignPatterns学习笔记:C++语言实现
  19. springcloud应用思考
  20. &lt;python数据挖掘入门与实战&gt;代码

热门文章

  1. Centos6.2上做nginx和tomcat的集成及负载均衡(已实践)
  2. Android ListView工作原理全然解析,带你从源代码的角度彻底理解
  3. Java 连接使用 Redis
  4. WPF入门教程系列三
  5. MVC之ActionFilterAttribute自定义属性
  6. Windows Mobile X图标如何销毁窗体而非隐藏
  7. centos7系统备份与还原
  8. eclipse中mat插件使用
  9. 2017-5-14 湘潭市赛 Similar Subsequence 分析+四维dp+一些简单优化
  10. Spring 3 MVC and JSR303 @Valid example