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

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

下面我们看下一个完整的操作流程,这样便于理解:
   首先我们要明白,重复提交是发生在什么情况下的,什么情况下需要处理重复提交。我们所要解决的重复提交一般是考虑用户新插入一条记录的情形,对于修改记录的重复提交一般不考虑,因为修改记录本身记录就存在ID,重复提交也只不过是重复更新数据库同一记录而已,对数据的正确性不会有影响。如果新插入一条记录不对重复提交进行处理的话,那么就会在数据库中重复插入同一记录,这样会在数据库产生冗余的重复记录。当我们要插入一条记录时,会分二步走。第一步我们要打开新增记录的页面。第二步,我们会在打开的页面中填写相关信息,然后提交,这个时候提交才算完成。
第一步:假如我们打开新增记录这个操作由add方法完成,代码如下:
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");

第二步:假如我们提交这个页面数据由save方法完成,代码如下:
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;
        }
2.然后再判断当前会话中是否存在令牌属性"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");

当用户重复提交时,我说了"this.saveToken(request);//此方法在这里可要也可不要。",下面我们分

析下,如果不调用这个方法,会话中就不会再重新保存token值,那么再刷新的时候,session中的token
值总是为null,isTokenValid(request)直接返回false,如果调用this.saveToken(request)的话,

session中会重新添加token属性值。这个时候isTokenValid(request)会进行下面第三步的判断。
3.从当前会话中取得token的值与当前request中得到的token值比较,相同返回true,不同返回false
  String token = request.getParameter("org.apache.struts.taglib.html.TOKEN");
        if (token == null) {
            return false;

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

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

struts token令牌机制的更多相关文章

  1. java:struts框架3(自定义拦截器,token令牌,文件上传和下载(单/多))

    1.自定义拦截器: struts.xml: <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ...

  2. 【Java EE 学习 36】【struts2】【struts2系统验证】【struts2 ognl值栈】【struts2 ongl标签】【struts2 UI标签】【struts2模型驱动和令牌机制】

    一.struts2系统验证 1.基于struts2系统验证的方式实际上就是通过配置xml文件的方式达到验证的目的. 2.实际上系统校验的方法和手工校验的方法在底层的基本实现是相同的.但是使用系统校验的 ...

  3. .NET WebAPI 用ActionFilterAttribute实现token令牌验证与对Action的权限控制

    项目背景是一个社区类的APP(求轻吐...),博主主要负责后台业务及接口.以前没玩过webAPI,但是领导要求必须用这个(具体原因鬼知道),只好硬着头皮上了. 最近刚做完权限这一块,分享出来给大家.欢 ...

  4. WebAPI 用ActionFilterAttribute实现token令牌验证与对Action的权限控制

    .NET WebAPI 用ActionFilterAttribute实现token令牌验证与对Action的权限控制 项目背景是一个社区类的APP(求轻吐...),博主主要负责后台业务及接口.以前没玩 ...

  5. day25(令牌机制)

    令牌机制 作用:处理页面重复提交,造成数据多次写入数据库. 使用方法: 类似于验证码机制,使用session记录一个不可能重复的值(Uuid)在访问controller时对session进行校验. / ...

  6. java- 综合实例-增删查改查,删除多项,分页,令牌机制

    重点内容:分页.令牌机制(重定向下防止重复提交).使用c3p0连接数据库(以及数据库连接类) 项目结构: 类: 项目展示: 数据库: /* SQLyog Ultimate v12.09 (64 bit ...

  7. 在ASP.NET Web API 2中使用Owin基于Token令牌的身份验证

    基于令牌的身份验证 基于令牌的身份验证主要区别于以前常用的常用的基于cookie的身份验证,基于cookie的身份验证在B/S架构中使用比较多,但是在Web Api中因其特殊性,基于cookie的身份 ...

  8. [Struts]Token 使用及原理

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

  9. Token令牌管理权限

    什么是token HTTP是一种无状态的协议,也就是HTTP没法保存客户端的信息,没办法区分每次请求的不同. Token是服务器生成的一串字符,作为客户端请求的令牌.当第一次登陆后,服务器会分发Ton ...

随机推荐

  1. selenium+python安装

    整理了下selenium+python环境搭建,搭建了很多次但每次都还是手忙脚乱,今天用心整理下 selenium 是用于测试 Web 应用程序用户界面 (UI) 的常用框架,并且 Selenium ...

  2. python 逻辑运算及奇怪的返回值(not,and,or)

    首先,'and'.'or'和'not'的优先级是not>and>or. 同一优先级从左往右计算. 先说非运算,Python的非运算与这些语言相比,并没有特别的地方.not只有两个返回值,T ...

  3. MATLAB菜鸟入门笔记【编程习惯】

    1.编程标记模板   %  Script file:temp_conversion.m % %  Purepose: %  To convert an input temperature from d ...

  4. (转载)字符编码那点事:快速理解ASCII、Unicode、GBK和UTF-8

  5. 10、mysql的调优

    mysql的调优 调优的最终目的:节省系统资源.提高响应速度下面从6个维度对mysql进行优化. 第一步:对服务器的参数进行调优 通过show profile命令分析,如果sql语句在执行过程中等待时 ...

  6. 云平台将故障Pod流量下线通用思路与OpenShift操作实战

    1 写在前边 自从公司项目前年上了 OpenShift 3.9 私有云平台,更新部署程序的确变得更加容易了.但是带来了很多复杂性,运维实施人员的学习曲线也陡然上升. 上云之前:在项目没上容器云的早期, ...

  7. 『现学现忘』Docker基础 — 26、Docker镜像分层的理解

    目录 1.分层的镜像 2.加深理解 3.特别说明 1.分层的镜像 我们可以去下载一个镜像,注意观察下载的日志输出,可以看到Docker的镜像是一层一层的在下载. 思考:为什么Docker镜像要采用这种 ...

  8. Redis pub/sub

    list 类型, lpush + rpop 或 lpush + brpop 用作消息队列时,消息只能消费一次,且不支持多个消费者(消息只能消费一次),并且在客户端崩溃时容易丢失消息.而 pub/sub ...

  9. 不带头结点的单链表(基于c语言)

    本篇文章的代码大多使用无头结点的单链表: 相关定义: #include <stdio.h> #include <stdlib.h> #include <assert.h& ...

  10. 昇腾CANN论文上榜CVPR,全景图像生成算法交互性再增强!

    摘要:近日,CVPR 2022放榜,基于CANN的AI论文<Interactive Image Synthesis with Panoptic Layout Generation>强势上榜 ...