利用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. php 命名规范

  2. jQuery-ajax-天气接口

    <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title> ...

  3. centos7下rsync+inotify脚本实现文件同步,.NET CORE客户端文件更新后自动重启服务

    源服务器IP:192.168.8.51 目标服务器IP:192.168.8.79 安装前源服务器及目标服务器均需关闭FIREWALLD\SELINUX防火墙 sestatus | grep statu ...

  4. MYSQL数年库安装

    MySQL系列 MySQL 的三大主要分支mysqlmariadbpercona Server MySQL系列2.2.2.1 MySQL 的三大主要分支mysqlmariadbpercona Serv ...

  5. idea Alt+Insert:构造函数

    Alt+Insert:构造函数 包含参数: Constructor:全参构造 Getter:必须的 return 字段名 Setter:this 值 Getter and Setter:选择字段以生成 ...

  6. LGP3281口胡

    当你看到一个东西的时候,GF 有可能比 DP 更方便.处理贡献也有可能比 DP 更方便. 这个题意明显是让我们计算 \(S(r)-S(l-1)\) 之类的东西( 所以直接考虑前缀的答案就好了( 考虑将 ...

  7. 跨平台跨架构的统信DTK开发套件教程及常见问题

    DTK是统信基于Qt开发的一整套简单且实用的通用开发框架,处于统信UOS系统中的核心位置,统信UOS浏览器.音乐.邮件等40余款原生应用全部使用DTK开发.DTK从开发者的角度出发,融合现代化的开发理 ...

  8. Eclipse阿里云镜像源配置

    镜像下载.域名解析.时间同步请点击 阿里巴巴开源镜像站 一.什么是Eclipse Eclipse 是一个开放源代码的.基于 Java 的可扩展开发平台.就其本身而言,它只是一个框架和一组服务,用于通过 ...

  9. HTTP发展史,HTTP1.1与HTTP2.0的区别

    前言 我们知道HTTP是浏览器中最重要且使用最多的协议,它不仅是浏览器与服务端的通信语言,更是互联网的基石.随着浏览器的不断更新迭代,HTTP为了适应技术的更新也在不断进化,学习HTTP的最佳途径就是 ...

  10. Dubbo 可以对结果进行缓存吗?

    为了提高数据访问的速度.Dubbo 提供了声明式缓存,以减少用户加缓存的工作 量 <dubbo:reference cache="true" /> 其实比普通的配置文件 ...