Web项目如何防止客户端重复发送请求

标签: java javascript web | 发表时间:2017-06-09 12:38 | 作者:chanjarster
出处:https://segmentfault.com/blogs

在Web项目中,有一些请求或操作会对数据产生影响(比如新增、删除、更新),针对这类请求一般都需要做一些保护,以防止用户有意或无意的重复发起这样的请求导致的数据错乱。

本文总结了一些防止客户端重复发送请求的方法。

方法一:JS监听Form的onsubmit事件

在经典场景下,浏览器通过Form发送请求。因此只需要在Form onsubmit时将Submit按钮disable,就能够防止用户双击导致的重复请求(这种问题一般发生在年纪大的用户身上,他们分不清单击和双击)。

但是随着前端的发展,Form以外的请求方式也越来越多,比如利用各种前端框架(Vue、AngularJs、Backbone等)写的App,他们更多的采用的是ajax的方式和后端交互。那么前端开发人员必须在开发时针对每个代表 发起请求的UI元素做处理,像Form一样,在发起请求的时候把相关UI元素 禁用掉。

而有些交互方式则可能连代表 发起请求的UI元素都没有,比如Segmentfault的markdown编辑器就是在一边输入的时候一边保存的。那么这时就需要前端代码采用其他手段来控制重复请求的发生。

优点:

  1. 不需要后端写代码

缺点:

  1. 不存在统一的解决方案,必须针对每种情况写处理代码

  2. 无法控制浏览器刷新发起的重复请求

  3. 前端开发人员忘记写相关代码

  4. 无法控制恶意的重复请求,比如绕过浏览器直接发起

方法二:Http Status Code 302(后端重定向)

服务端采用重定向的方式,防止用户刷新浏览器发出重复请求。这是比较经典的后端控制重复请求的方式,因为一旦 重定向成功后,用户刷新浏览器所刷新的是那个重定向地址,而不是数据操作地址。

优点:

  1. 不需要写前端代码

缺点:

  1. 在还未响应302之前,所发起的重复请求,比如:用户快速的双击、刷新浏览器

  2. 在某些前端程序里(比如SPA),不能使用重定向

  3. 后端开发人员忘记写相关代码

  4. 无法控制恶意的重复请求,比如绕过浏览器直接发起

方法三:结合方法一和方法二

结合方法一和方法二的话倒是可以解决大部分问题,但是解决不了以下问题:

  1. 在还未响应302之前,用户刷新浏览器导致的重复请求

  2. 有些场景下压根不能使用重定向

  3. 前、后端开发人员忘记写相关代码

  4. 无法控制恶意的重复请求,比如绕过浏览器直接发起

方法四:token方式

token的流程是这样的:

  1. 在浏览器发送请求前,先到服务端索要token

  2. 浏览器发送请求时,将token一并提交

  3. 服务端检查请求是否携带token、token是否有效(比如是否正确、是否过期)。如果不正确则响应失败;如果正确则销毁token,继续业务逻辑。

关键点在于:

  1. 每个token都是一次性且有过期时间的,能够防止token前端程序bug造成的重复利用和无限利用,能够避免前端开发人员代码bug。

  2. 服务器要求请求必须携带token,能够避免前端开发人员漏写相关代码

那么token是以怎样的形式传输的呢?我认为有以下两种方式:

Cookie

推荐使用这种方式,因为浏览器每次都会将cookie携带在请求里一并发出,所以前端发送请求的代码都不需要修改,只要在发送请求前问服务器拿token就行了。

比如在进入Form页面时,服务器将token以cookie的形式一并携带在响应中,那么前端Form提交时,就会将cookie一并携带在请求中,前端的代码一点都不需要修改。

json

前端发起ajax请求像后端拿token,后端以json的形式返回token,前端发送请求时将token携带在请求中,后端检验。

这种方式比Cookie稍微麻烦的地方是,前端必须写一些代码来保存这个token,然后在发送请求的地方要写一些代码把token携带在请求里。

优点

  1. 前端代码可以写的少一些,比如禁用UI元素的代码可以不写

  2. 能够解决在还未响应302之前,用户刷新浏览器导致的重复请求

  3. 适应有些场景下压根不能使用重定向

缺点

  1. 前、后端开发人员忘记写相关代码。这个真的解决不了。

  2. 无法控制通过脚本运行的,具有整套流程的恶意请求。这种请求在程序看来完全合法,但却属于恶意行为,针对这类恶意行为的防控属于另一个话题,本人不懂,所以在这里就不多讲了。

相关 [web 项目 客户端] 推荐:

Web项目如何防止客户端重复发送请求

- - SegmentFault 最新的文章
在Web项目中,有一些请求或操作会对数据产生影响(比如新增、删除、更新),针对这类请求一般都需要做一些保护,以防止用户有意或无意的重复发起这样的请求导致的数据错乱. 本文总结了一些防止客户端重复发送请求的方法. 方法一:JS监听Form的onsubmit事件. 在经典场景下,浏览器通过Form发送请求.

web项目经理手册

- - 研发管理 - ITeye博客
        web项目指基于web的开发项目,由于web开发的一些特点,使得web开发的项目管理与以往的软件开发项目管理有很大的不同,具体表现在.         一般的web项目的周期为1~3月,而一般的软件开发的周期都在半年以上,象vista微软花费了五年的时间才开发出来.         互联网公司推出的产品,讲究快字当头,谁先推出产品占领市场,谁就取得先机,所以web的项目往往要求上线快,对于比较大的项目通常我们会先把产品先launch上线,然后第二期第三期再来完善.

十问Web网站项目

- - 博客园_新闻
英文原文: 10 Important Questions to Ask About Your Next Website Project. Ltd 开发者 Richa Jain 在本文中为我们带来了一个有趣的话题:在一个 Web 网站项目中,我们应该问自己十个这样的问题. 如果你在开发的过程中存在疑惑,或许你可以在本文中获得帮助.

iOS客户端开发与Web前端开发

- - bang's blog
不知不觉做iOS客户端开发已经半年多了,了解到iOS客户端开发与Web前端开发的一些异同,写一下. 用户角度上看,客户端升级必须让用户手动下载整个新的安装包覆盖安装,而web的升级无需用户做任何事情. 开发角度上看,如果客户端有个小bug需要紧急修复,需要修复完后打包一个完成的安装包,给一个版本号,发布给用户升级.

Web客户端安全性最佳实践

- - 博客 - 伯乐在线
得益于HTML5,Web应用中越来越多的逻辑从服务器端迁移到了客户端. 因而,前端开发人员也需要更多关注安全性方面的问题. 在这篇文章中,我会告诉你如何使你的应用更加安全. 我会着重描述一些你可能从未听说过的技术,而不是仅仅告诉你“别忘了对用户提交的页面数据做转义(escape)”. 当然,我并不想让你通过FTP或者普通的TCP协议来传输你的数据.

xssProject在java web项目中应用

- - Java - 编程语言 - ITeye博客
1.项目引入xssProtect-0.1.jar、antlr-3.0.1.jar、antlr-runtime-3.0.1.jar包. * 覆盖getParameter方法,将参数名和参数值都做xss过滤. * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取
.

eclipse如何导入myeclipse的web项目

- - 开源软件 - ITeye博客
1、进入项目目录,找到.project文件,打开. 2、找到...代码段. 3、在第2步的代码段中加入如下标签内容并保存:. 4、项目目录下的.classpath文件,把所有Webroot字符串改为WebContent,保存. 5、把目录下webroot的文件夹改名为WebContent.

Web项目管理工具精选

- - 行业应用 - ITeye博客
以前各种开源项目的代码都是通过博客和个人网页来发布的. 这种分享方式并不是最容易的一种,也不便于他人对代码做出贡献. 下面是几个管理项目代码的工具,不管对于个人开发者还是团队开发者来说,它们都是非常好用的. GitHub,也就是Git版本控制系统,采用一种优雅的方式来管理项目代码. 比起Subversion,Git要更加经济划算,对于新手来说安装过程也更加简单.

在 Web 项目中应用 Apache Shiro

- - 企业架构 - ITeye博客
Apache Shiro 是功能强大并且容易集成的开源权限框架,它能够完成认证、授权、加密、会话管理等功能. 认证和授权为权限控制的核心,简单来说,“认证”就是证明你是谁. Web 应用程序一般做法通过表单提交用户名及密码达到认证目的. “授权”即是否允许已认证用户访问受保护资源. 关于 Shiro 的一系列特征及优点,很多文章已有列举,这里不再逐一赘述,本文重点介绍 Shiro 在 Web Application 中如何实现验证码认证以及如何实现单点登录.

使用Spring Boot开发Web项目

- - ImportNew
前面两篇博客中我们简单介绍了spring Boot项目的创建、并且也带小伙伴们来DIY了一个Spring Boot自动配置功能,那么这些东西说到底最终还是要回归到Web上才能体现出它的更大的价值,so,今天我们就来看一下如何使用Spring Boot来开发Web项目. 当然,如果小伙伴对Spring Boot尚不熟悉的话,可以先参考一下这两篇博客:.