`
wsqwsq000
  • 浏览: 676238 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

saveToken(request)

    博客分类:
  • j2ee
 
阅读更多

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

 
public ActionForward add(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  //前面的处理省略
  
  saveToken(request);
  
  return mapping.findForward("add");
  
  }在Action的insert方法中,我们根据表单中的Token值与服务器端的Token值比较,如下所示:
  
  public ActionForward insert(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  if (isTokenValid(request, true)) {
  
  // 表单不是重复提交
  
  //这里是保存数据的代码
  
  } else {
  
  //表单重复提交
  
  saveToken(request);
  
  //其它的处理代码
  
  }
  
  }
  
 

其实使用起来很简单,举个最简单、最需要使用这个的例子:
  
  一般控制重复提交主要是用在对数据库操作的控制上,比如插入、更新、删除等,由于更新、删除一般都是通过id来操作(例如:updateXXXById, removeXXXById),所以这类操作控制的意义不是很大(不排除个别现象),重复提交的控制也就主要是在插入时的控制了。
  
  先说一下,我们目前所做项目的情况:
  
  目前的项目是用Struts+Spring+Ibatis,页面用jstl,Struts复杂View层,Spring在Service层提供事务控制,Ibatis是用来代替JDBC,所有页面的访问都不是直接访问jsp,而是访问Structs的Action,再由Action来Forward到一个Jsp,所有针对数据库的操作,比如取数据或修改数据,都是在Action里面完成,所有的Action一般都继承BaseDispatchAction,这个是自己建立的类,目的是为所有的Action做一些统一的控制,在Struts层,对于一个功能,我们一般分为两个Action,一个Action里的功能是不需要调用Struts的验证功能的(常见的方法名称有add,edit,remove,view,list),另一个是需要调用Struts的验证功能的(常见的方法名称有insert,update)。
  
  就拿论坛发贴来说吧,论坛发贴首先需要跳转到一个页面,你可以填写帖子的主题和内容,填写完后,单击“提交”,贴子就发表了,所以这里经过两个步骤:
  
  1、转到一个新增的页面,在Action里我们一般称为add,例如:

 public ActionForward add(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  throws Exception {
  
  //这一句是输出调试信息,表示代码执行到这一段了
  
  log.debug(":: action - subject add");
  
  //your code here
  
  //这里保存Token值
  
  saveToken(request);
  
  //跳转到add页面,在Structs-config.xml里面定义,例如,跳转到subjectAdd.jsp
  
  return mapping.findForward("add");
  
  }
  

public ActionForward insert(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response){
  
  if (isTokenValid(request, true)) {
  
  // 表单不是重复提交
  
  //这里是保存数据的代码
  
  } else {
  
  //表单重复提交
  
  saveToken(request);
  
  //其它的处理代码
  
  }
  
  }
  
 
下面更详细一点(注意,下面所有的代码使用全角括号):
  
  1、你想发贴时,点击“我要发贴”链接的代码可以里这样的:
  
  〈html:link action="subject.do?method=add"〉我要发贴〈/html:link〉
  
  subject.do 和 method 这些在struct-config.xml如何定义我就不说了,点击链接后,会执行subject.do的add方法,代码如上面说的,跳转到subjectAdd.jsp页面。页面的代码大概如下:
  
  〈html:form action="subjectForm.do?method=insert"〉
  
  〈html:text property="title" /〉
  
  〈html:textarea property="content" /〉
  下面更详细一点(注意,下面所有的代码使用全角括号):
  
  1、你想发贴时,点击“我要发贴”链接的代码可以里这样的:
  
  〈html:link action="subject.do?method=add"〉我要发贴〈/html:link〉
  
  subject.do 和 method 这些在struct-config.xml如何定义我就不说了,点击链接后,会执行subject.do的add方法,代码如上面说的,跳转到subjectAdd.jsp页面。页面的代码大概如下:
  
  〈html:form action="subjectForm.do?method=insert"〉
  
  〈html:text property="title" /〉
  
  〈html:textarea property="content" /〉
  
  〈html:submit property="发表" /〉
  
  〈html:reset property="重填" /〉
  
  〈html:form〉
  
  如果你在add方法里加了“saveToken(request);”这一句,那在subjectAdd.jsp生成的页面上,会多一个隐藏字段,类似于这样〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,
  
  2、点击发表后,表单提交到subjectForm.do里的insert方法后,你在insert方法里要将表单的数据插入到数据库中,如果没有进行重复提交的控制,那么每点击一次浏览器的刷新按钮,都会在数据库中插入一条相同的记录,增加下面的代码,你就可以控制用户的重复提交了。


  〈html:submit property="发表" /〉
  
  〈html:reset property="重填" /〉
  
  〈html:form〉
  
  如果你在add方法里加了“saveToken(request);”这一句,那在subjectAdd.jsp生成的页面上,会多一个隐藏字段,类似于这样〈input type="hidden" name="org.apache.struts.taglib.html.TOKEN" value="6aa35341f25184fd996c4c918255c3ae"〉,
  
  
if (isTokenValid(request, true)) {
  
  // 表单不是重复提交
  
  //这里是保存数据的代码
  
  } else {
  
  //表单重复提交
  
  saveToken(request);
  
  //其它的处理代码
  
  }
注意,你必须在add方法里使用了saveToken(request),你才能在insert里判断,否则,你每次保存操作都是重复提交。
  
  记住一点,Struts在你每次访问Action的时候,都会产生一个令牌,保存在你的Session里面,如果你在Action里的函数里面,使用了saveToken(request);,那么这个令牌也会保存在这个Action所Forward到的jsp所生成的静态页面里。
  
  如果你在你Action的方法里使用了isTokenValid,那么Struts会将你从你的request里面去获取这个令牌值,然后和Session里的令牌值做比较,如果两者相等,就不是重复提交,如果不相等,就是重复提交了。
  
  由于我们项目的所有Action都是继承自BaseDispatchAction这个类,所以我们基本上都是在这个类里面做了表单重复提交的控制,默认是控制add方法和insert方法,如果需要控制其它的方法,就自己手动写上面这些代码,否则是不需要手写的,控制的代码如下:

 
 
public abstract class BaseDispatchAction extends BaseAction {
  
  protected ActionForward perform(ActionMapping mapping, ActionForm form,
  
  HttpServletRequest request, HttpServletResponse response)
  
  throws Exception {
  
  String parameter = mapping.getParameter();
  
  String name = request.getParameter(parameter);
  
  if (null == name) { //如果没有指定 method ,则默认为 list
  
  name = "list";
  
  }
  
  if ("add".equals(name)) {
  
  if ("add".equals(name)) {
  
  saveToken(request);
  
  }
  
  } else if ("insert".equals(name)) {
  
  if (!isTokenValid(request, true)) {
  
  resetToken(request);
  
  saveError(request, new ActionMessage("error.repeatSubmit"));
  
  log.error("重复提交!");
  
  return mapping.findForward("error");
  
  }
  
  }
  
  return dispatchMethod2(mapping, form, request, response, name);
  
  }
  
  }
2、在填写标题和内容后,选择 提交 ,会提交到insert方法,在insert方法里判断,是否重复提交了。
 
 

分享到:
评论

相关推荐

    sturts1 解决主键刷新冲突

    重复提交 主键 刷新 冲突 saveToken 当我们在页面点击新增的时候,提交完成。这时我们在页面点右键刷新会出现主键冲突的错误,struts1 已解决!

    221217-003-admin(前端之全局存储:Vuex=Store)

    第17章 前端之全局存储:Vuex=Store Store用于对数据进行存储,并共享以为所有需要的Vue页面中的调用提供数据及其方法支撑;Vuex是Store的内置引用包,即... saveToken: function(state, data) { state.token = data;

    ts-api-toolkit:带有(Red)axios的包装器,结合了Json Web令牌处理,可以轻松地与API进行通信,无论是否经过授权

    TS-API-工具包 TS-API-Toolkit是处理API调用以及localStorage JWT管理的简单方法。 该库提供了围绕的简单包装,并提供了处理JWT的服务。... saveToken ( user . token ) ;原料药该库提供了两个类实例导出, ApiSe

    node-v6.15.0-darwin-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    本人通过学习动手学习深度学习这本书后,跟着书本写出的基于pytorch的练习集合.zip

    本人通过学习动手学习深度学习这本书后,跟着书本写出的基于pytorch的练习集合.zip

    node-v6.11.5-linux-ppc64le.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    基于UCC21520DWR驱动 TI维也纳PFC电源板AD设计硬件原理图+PCB工程文件.zip

    基于UCC21520DWR驱动 TI维也纳PFC电源板AD设计硬件原理图+PCB工程文件,Altium Designer 设计的工程文件,包括原理图及PCB文件,4层板设计,板子大小为258x236mm,双面布局布线,可以用Altium(AD)软件打开或修改,可作为你产品设计的参考。

    node-v0.11.16-linux-x86.tar.gz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    抖音数据可视化分析系统技术框架python + flask web + mysql角色介绍管理员admin

    微博热搜数据可视化分析系统 技术框架 python + flask web + mysql 角色介绍 管理员 admin 123456 模块分析 登录模块 可视化模块 趋势模块(折线图) 热搜模块(云词图) 最大最小(饼图) 前几个热度(柱状图) 分析模块 情感分析模块 (因为舆情分析包含了情感分析我们为了区分两者的区别在舆情模块中包含了中文分词jiba功能) 影响分析模块 (影响分析我们根据数据库中的数据来分析,主要做两部获取数据库中最大的热度标题,jiba分词获取出现频率最大的热搜,和最小的热搜) 舆情分析模块 (单独的使用snow就行因为舆情分析包含了情感分析) 爬虫模块 (页面上有一个爬虫按钮,当用户点击以后它爬出一次热搜的数据并添加到数据库中) 违规词模块 密码重置模块 四个个页面 登录 ,首页, 可视化, 分析类 首页页面 (首页类似的导航页面,它有一个关键的按钮就是启动爬虫,爬取最新热搜) 可视化页面 (从数据库中加载不同时间段的热搜数据,并以折线图,和云词图显示) 分析类页面 (主要三个模块:“情感分析模块,影响分析

    node-v6.10.3-linux-s390x.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    SSM+JSP项目-汽车售后服务管理系统的Java毕业设计(源码+演示视频+说明).rar

    SSM+JSP项目-汽车售后服务管理系统的Java毕业设计(源码+演示视频+说明).rar 【项目技术】 开发语言:Java 框架:ssm+jsp 架构:B/S 数据库:mysql 【演示视频-编号:413】 https://pan.quark.cn/s/b3a97032fae7 【实现功能】 系统可以提供信息显示和相应服务,本系统管理员管理员工,管理材料,管理材料出入库订单,管理公告以及维修类型信息。员工对材料进行入库,出库,管理维修预约信息。用户新增维修预约信息,查看维修进度,查看材料信息,查看公告。

    电源设计培训PPT资料开关电源技术讲解明纬开关电源技术资料等合集(14个).zip

    电源设计培训PPT资料开关电源技术讲解明纬开关电源技术资料等合集(14个): 准谐振和同步整流技术在反激变换器中的应用.ppt 反激式开关电源变压器设计.ppt 台湾明纬开关电源技术资料.pdf 台达开关电源介绍.ppt 台达开关电源基本原理介绍.ppt 各种开关电源技术讲解.ppt 图文解说开关电源.doc 明纬开关电源09年10月份样本.pdf 模块电源培训讲义.pdf 用於AC-DC电源的产品.ppt 电子元件培训教材.ppt 电源培训.ppt 高压直流供电技术交流.ppt 高效率开关电源设计3.ppt

    基于Matlab的指纹识别系统.zip

    基于MATLAB的系统

    基于计算机视觉和深度学习,使用pygame模拟手柄操作,实现欧卡2的自动驾驶(未完成,学习AI中...).zip

    基于计算机视觉和深度学习,使用pygame模拟手柄操作,实现欧卡2的自动驾驶(未完成,学习AI中...).zip

    node-v0.12.11-x86.msi

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v6.11.3-linux-x86.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    node-v6.1.0-linux-x64.tar.xz

    Node.js,简称Node,是一个开源且跨平台的JavaScript运行时环境,它允许在浏览器外运行JavaScript代码。Node.js于2009年由Ryan Dahl创立,旨在创建高性能的Web服务器和网络应用程序。它基于Google Chrome的V8 JavaScript引擎,可以在Windows、Linux、Unix、Mac OS X等操作系统上运行。 Node.js的特点之一是事件驱动和非阻塞I/O模型,这使得它非常适合处理大量并发连接,从而在构建实时应用程序如在线游戏、聊天应用以及实时通讯服务时表现卓越。此外,Node.js使用了模块化的架构,通过npm(Node package manager,Node包管理器),社区成员可以共享和复用代码,极大地促进了Node.js生态系统的发展和扩张。 Node.js不仅用于服务器端开发。随着技术的发展,它也被用于构建工具链、开发桌面应用程序、物联网设备等。Node.js能够处理文件系统、操作数据库、处理网络请求等,因此,开发者可以用JavaScript编写全栈应用程序,这一点大大提高了开发效率和便捷性。 在实践中,许多大型企业和组织已经采用Node.js作为其Web应用程序的开发平台,如Netflix、PayPal和Walmart等。它们利用Node.js提高了应用性能,简化了开发流程,并且能更快地响应市场需求。

    一种在基于深度学习的侧信道攻击中网格调参的方法.zip

    一种在基于深度学习的侧信道攻击中网格调参的方法.zip

    流水线包裹检测数据集VOC+YOLO格式145张4类别.zip

    数据集格式:Pascal VOC格式+YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):145 标注数量(xml文件个数):145 标注数量(txt文件个数):145 标注类别数:4 标注类别名称:["bag","bigbox","box","longbox"] 每个类别标注的框数: bag 框数 = 238 bigbox 框数 = 19 box 框数 = 309 longbox 框数 = 9 总框数:575 使用标注工具:labelImg 标注规则:对类别进行画矩形框 重要说明:暂无 特别声明:本数据集不对训练的模型或者权重文件精度作任何保证,数据集只提供准确且合理标注

    基于SSM+JSP的淘乐乐员工购物商城毕业设计(源码+录像+说明).rar

    基于SSM+JSP的淘乐乐员工购物商城毕业设计(源码+录像+说明).rar 【项目技术】 开发语言:Java 框架:ssm+jsp 架构:B/S 数据库:mysql 【演示视频-编号:494】 https://pan.quark.cn/s/b3a97032fae7 【实现功能】 系统可以提供信息显示和相应服务,其管理员增删改查商品信息和商品信息资料,审核商品信息预订订单,查看订单评价和评分,通过留言功能回复用户提问。

Global site tag (gtag.js) - Google Analytics