使用struts的同步令牌避免form的重复提交

一、使用方法

1  假如你要提交的页面为toSubmit.jsp

2  在打开toSubmit.jspAction1 中加入:saveToken(request) ,例如

public ActionForward execute(

    ActionMapping mapping,

    ActionForm form,

    HttpServletRequest request,

    HttpServletResponse response)

    throws Exception {

   

        // 生成同步令牌

        saveToken(request);    

 

        return mapping.findForward("toSubmit");

}

3  在提交toSubmit.jspAction2 中加入: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> 时,便会调用strutsFormTag 类,其中有一个方法:

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);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值