Struts 中的 Token 机制

背景

在提交表单的时候,通常有一种情况是新增加一条记录。当新增成功的时候,跳到添加成功的界面,如果用户点击了浏览器的回退,转到刚才的提交页面,再次点击提交。此时如果没有做处理,就会发生重复提交的问题。如果新插入一条记录不对重复提交进行处理的话,那么就会在数据库中重复插入同一记录,这样会在数据库产生冗余的重复记录。

Token 机制

Struts中的Token机制,实际上就是通过用户提交表单时,比较request中的请求参数org.apache.struts.taglib.html.TOKEN的值与当前会话中的属org.apache.struts.action.TOKEN的值是否相等,相等则是正常提交,不等则为重复提交。

 if (isTokenValid(request, true)) {
       // 未重复提交时,正确的时候应该做的事情
    return mapping.findForward("success");
} else {
    // 重复提交时,需要做的事情
    saveToken(request);
    return mapping.findForward("error");
} 

处理过程

1. 新增一条记录时

在转到新增界面的action中

public ActionForward add(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) { 
  this.saveToken(request);//这个方法就是产生令牌值,struts已有的方法 
  return mapping.findForward("add");//返回新增页面
}

通过调用saveToken(request),产生一个token值。(注:每次调用saveToken方法产生的token值都不同)

然后在记录新增页面中的<html:form>内部增加一个隐含表单字段,形式如下:

<div>
  <input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="8b2d950f23b02c527988a14171254025">
</div>

然后再把token值8b2d950f23b02c527988a14171254025保存到当前会话中,也就是 session.setAttribute( "org.apache.struts.action.TOKEN","8b2d950f23b02c527988a14171254025");

2. 提交的数据保存

public ActionForward save(ActionMapping mapping, ActionForm form,
   HttpServletRequest request, HttpServletResponse response) { 
  if (this.isTokenValid(request)) {//正常提交
   //其它业务操作......
   this.resetToken(request);//清空当前会话中的token值
   return mapping.findForward("success");//返回保存成功页面
  } else {//重复提交   
   this.saveToken(request);//注:此方法在这里可要也可不要。  
   return mapping.findForward("fail");//返回重复提交提示信息页面
  }
}

判断是不是重复提交关键是isTokenValid(request)这个方法,这个方法由struts提供,如果返回结果为true则表示正常提交,false则为重复提交。isTokenValid(request)这个方法实际上主要做了三件事,

  1. 判断当前会话是否过期,如果过期,直接返回false
HttpSession session = request.getSession(false);
if (session == null) {
    return false;
}
  1. 然后再判断当前会话中是否存在令牌属性org.apache.struts.action.TOKEN,如果不存在,返回false
String saved =(String) session.getAttribute("org.apache.struts.action.TOKEN");
if (saved == null) {
    return false;
}

为什么令牌属性org.apache.struts.action.TOKEN会不存在呢,那是因为当用户正常提交后,会调用this.resetToken(request);//清空当前会话中的token值。也就是说resetToken(request)方法中调用了 session.removeAttribute("org.apache.struts.action.TOKEN");

3 .从当前会话中取得token的值与当前request中得到的token值比较,相同返回true,不同返回false

String token = request.getParameter("org.apache.struts.taglib.html.TOKEN");
if (token == null) {
    return false;
}
return saved.equals(token);

如果是重复刷新,那么每次request中的令牌值都是一样的,但每次刷新当前会话中的令牌值都被重新替换了,所以会返回false

:使用struts的表单提交Token机制时,提交的表单一定要写成<html:form></html:form>这种形式,如果写成<form></form>这种形式的话,尽管调用saveToken(request)方法也不会在当前的<form></form>里面生成隐含表单,最终的结果都是"重复提交".

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 135,810评论 19 139
  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 32,312评论 18 399
  • 概述 Struts就是基于mvc模式的框架!(struts其实也是servlet封装,提高开发效率!) Strut...
    奋斗的老王阅读 8,170评论 0 51
  • (一)Struts、Spring、Hibernate、Mybatis框技术 1.Struts2.0有几种标签库 【...
    独云阅读 8,533评论 0 62
  • 任谁的耐心都是有限的 终究会被磨光 如果说我相信一开始你是有点喜欢我的 那现在 你的耐心已经被我消耗殆尽了吧 你不...
    菀卿阅读 1,769评论 1 0

友情链接更多精彩内容