`

Struts中防止刷新重复提交令牌的用法(防止刷新或防止重复提交数据库)

    博客分类:
  • J2EE
阅读更多

Struts的Token(令牌)机制能够很好的解决表单重复提交的问题.
基本原理是:服务器端在处理到达的请求之前,会将请求中包含的令牌值与保存在当前用户会话中的令牌值进行比较,看是否匹配。在处理完该请求后,且在答复发送给客户端之前,将会产生一个新的令牌,该令牌除传给客户端以外,也会将用户会话中保存的旧的令牌进行替换。这样如果用户回退到刚才的提交页面并再次提交的话,客户端传过来的令牌就和服务器端的令牌不一致,从而有效地防止了重复提交的发生。
这时其实也就是两点,第一:你需要在请求中有这个令牌值,请求中的令牌值如何保存,其实就和我们平时在页面中保存一些信息是一样的,通过隐藏字段来保存,保存的形式如:
〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,
这个value是TokenProcessor类中的generateToken()获得的,是根据当前用户的session id和当前时间的long值来计算的。第二:在客户端提交后,我们要根据判断在请求中包含的值是否和服务器的令牌一致,因为服务器每次提交都会生成新的 Token,所以,如果是重复提交,客户端的Token值和服务器端的Token值就会不一致。

一、使用方法
1、 假如你要提交的页面为toSubmit.jsp;
2、 在打开toSubmit.jsp的Action1 中加入:saveToken(request),例如
public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws Exception {
        //生成同步令牌
        saveToken(request);   
        return mapping.findForward("toSubmit");
}

3、 在提交toSubmit.jsp的Action2 中加入:isTokenValid(request, true),例如:
public ActionForward execute(
    ActionMapping mapping,
    ActionForm form,
    HttpServletRequest request,
    HttpServletResponse response)
    throws Exception {
    // 验证同步令牌
        if (isTokenValid(request, true)) {
            //执行提交操作
        }else {
            // 重复提交       
            return mapping.findForward("Error");
        }
}

4、 使用注意:toSubmit.jsp中的form必须使用 struts的标签<html:form>。

二、基本原理

第一步、在session中放入同步令牌
在Action1中加入了saveToken(request)的方法后,调用TokenProcessor 类的saveToken方法如下:
public synchronized void saveToken(HttpServletRequest request) {
    HttpSession session = request.getSession();
    String token = generateToken(request);
    if (token != null) {
        session.setAttribute(Globals.TRANSACTION_TOKEN_KEY, token);
    }
}

很明显在session中放入了同步令牌,名称为Globals.TRANSACTION_TOKEN_KEY。

第二步、在页面创建hidden元素
当应用服务器初始化toSubmit.jsp页面遇到标签<html:form>时,便会调用struts 的FormTag类,其中有一个方法:
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();
}

其意为:当检测到session中的Globals.TRANSACTION_TOKEN_KEY不为空时,在 toSubmit.jsp页面创建元素:
<input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="">
名称为:org.apache.struts.taglib.html.TOKEN就是 Constants.TOKEN_KEY;
值为:session中的Globals.TRANSACTION_TOKEN_KEY的值,即为同步令牌值。

第三步、验证同步令牌
在Action2中加入isTokenValid方法,实际上是调用TokenProcessor类的 isTokenValid方法如下:
public synchronized boolean isTokenValid(
    HttpServletRequest request,
    boolean reset) {
    // Retrieve the current session for this request
    HttpSession session = request.getSession(false);
    if (session == null) {
        return false;
    }
    // Retrieve the transaction token from this session, and
    // reset it if requested
    String saved = (String) session.getAttribute(Globals.TRANSACTION_TOKEN_KEY);
    if (saved == null) {
        return false;
    }
    if (reset) {
        this.resetToken(request);
    }
    // Retrieve the transaction token included in this request
    String token = request.getParameter(Constants.TOKEN_KEY);
    if (token == null) {
        return false;
    }
    return saved.equals(token);
}


它首先取得session中的令牌值,然后resetToken,再从页面hidden元素取来令牌值,进行比较,如果相等则为第一次,不等则为重复提交。
其中resetToken方法如下:
public synchronized void resetToken(HttpServletRequest request) {
    HttpSession session = request.getSession(false);
    if (session == null) {
        return;
    }
    session.removeAttribute(Globals.TRANSACTION_TOKEN_KEY);
}

分享到:
评论

相关推荐

    struts2_token控制刷新重复提交

    在Web开发中,处理用户提交的数据时,防止重复提交是一个常见的需求,特别是对于那些可能会改变系统状态的操作,如添加、删除或修改数据。Struts2提供了一种名为“token”的机制来解决这个问题。 **什么是Token机制...

    Struts解决重复提交步骤

    令牌机制是Struts框架用于防止表单重复提交的一种手段。其基本原理是在客户端与服务器之间传递一个随机生成的唯一标识符(即令牌),通过对比客户端提交时携带的令牌与服务器端存储的令牌是否一致来判断请求是否有效...

    防止表单重复提交

    这可能导致数据库中插入相同的数据,或者执行多次不应重复执行的操作。 防止表单重复提交的常见策略有以下几种: 1. **客户端验证**:在JavaScript中,可以监听表单提交事件,一旦表单提交,禁用提交按钮,防止...

    Struts高级部分(1)(解决重复提交、上传组件)

    本节主要关注Struts在处理两个关键问题上的高级应用:防止重复提交和文件上传组件的使用。 **一、解决重复提交** 在Web应用程序中,重复提交是一个常见的问题,可能导致数据不一致或服务过载。Struts通过几种策略...

    Struts之Token解决表单那重复提交

    在Struts配置文件中,为需要防止重复提交的Action添加一个拦截器引用,如`token`或`token-session`。这两个拦截器都可以处理Token,但`token-session`更安全,因为它会将Token存储在会话中,而不仅仅是请求中。 2....

    JSP_重复提交_解决方法

    **场景说明**:重复提交和刷新通常发生在用户操作过程中,特别是在提交表单后,如果用户不知道操作是否成功完成,可能会尝试刷新页面或重复点击提交按钮,这就会导致数据被重复提交到服务器。 **是否需要处理**:...

    Java怎样防止重复提交

    在Java Web开发中,防止重复提交是一个重要的议题,尤其是在大型分布式应用中,因为这可能导致服务器资源的过度消耗,甚至引发系统性能问题。以下是一些防止重复提交的常见策略和技术: 1. **令牌(Token)机制**:...

    防重复提交代码

    本篇文档介绍了一种在Java Web开发中防止JSP刷新造成的重复提交的方法。这种方法通过利用会话(Session)和令牌(Token)机制来实现,确保即使在用户刷新页面的情况下,也只允许一次有效提交。 #### 三、具体实现...

    jsp中StrutsToken令牌

    StrutsToken是在Java Web开发中,特别是基于Struts框架的应用中,用来防止重复提交的一种机制。在Web应用中,用户可能会无意或有意地多次点击提交按钮,导致服务器接收到重复的请求,这可能会对数据库或其他后端服务...

    sturts1 解决主键刷新冲突

    在处理用户交互时,如果用户重复提交表单,可能会导致主键冲突,因为相同的主键值被尝试插入到数据库中。 为了解决这种冲突,Struts1框架提供了一种称为“令牌验证”的机制。这个机制的主要目的是防止重复提交,也...

    JavaWeb中HttpSession中表单的重复提交示例

    在JavaWeb开发中,表单的重复提交是一个常见的问题,可能导致数据的异常处理或数据库的冗余操作。本示例主要关注如何利用HttpSession来防止这种情况的发生。 重复提交通常发生在以下几种场景: 1. 用户提交表单后,...

    SSH+DWR 用户登录注册(无刷新验证)

    在用户登录或注册过程中,传统方式是在用户输入完成后提交表单,然后服务器端进行验证,如果失败则返回错误信息,整个过程会刷新页面。无刷新验证则是通过DWR,当用户输入时立即在后台进行验证,实时反馈错误信息,...

    Java+Ajax+struts2的web网页聊天

    5. **安全考虑**:在实现Web聊天时,还需关注安全性问题,如防止XSS(跨站脚本攻击)、CSRF(跨站请求伪造)等,可以通过对用户输入进行过滤、使用安全的编码方式、设置CSRF令牌等方式加强防护。 6. **性能优化**:...

    AJAX入门与相关例子(整合SSH)

    2. **安全考虑**:防止跨站脚本攻击(XSS)、跨站请求伪造(CSRF)等,使用验证码、令牌等机制增强安全性。 3. **性能优化**:减少 AJAX 请求的大小和频率,利用 JSONP、CORS 等技术解决跨域问题,提升用户体验。 ...

    java_学习资料

    - **目的**:防止表单重复提交。 - **实现**:通过在表单中添加一个隐藏字段,并在提交表单前验证该字段的值是否有效。 **文件上传** - **原理**:使用MultipartRequest来处理含有文件的HTTP请求。 - **实现**:...

    网上购物系统

    学习这部分可以帮助理解如何在数据库中持久化购物车状态,以及如何处理并发操作。 8. **支付集成**:真实的购物系统往往需要与第三方支付平台(如PayPal、支付宝等)进行接口对接。这涉及API调用、交易状态跟踪以及...

    ajax开发的java留言程序

    - 动态加载:使用Ajax获取新留言,动态插入到页面中,无需刷新页面。 - 回复功能:用户可以回复其他人的留言,同样通过Ajax实现。 - 分页显示:如果留言过多,可以采用分页技术,每页展示一定数量的留言。 7. **...

    Ajax+Java开发实例源文件

    用户可以一边查看页面内容,一边在后台加载或提交数据,提升了应用的响应速度。 3. **数据格式**:虽然名称中包含XML,但实际Ajax传输的数据格式可以是XML、JSON、HTML或其他格式。在现代Web开发中,JSON因其轻量级...

    前后端分离的火车票管理系统.zip

    【标题】"前后端分离的火车票管理系统"是一款基于JSP、Java Web技术,并结合Servlet框架和MySQL数据库的毕业设计或课程设计项目。这个系统旨在实现一个完整的购票流程,包括用户登录、查询车票、预定及支付等功能,...

Global site tag (gtag.js) - Google Analytics