zoukankan      html  css  js  c++  java
  • ASP.NET 重复点击请求导致数据库中出现重复

    产生原因

    由于重复点击或者网络重发

    eg:

    点击提交按钮两次;

    点击刷新按钮;

    使用浏览器后退按钮重复之前的操作,导致重复提交表单;

    使用浏览器历史记录重复提交表单;

    浏览器重复的HTTP请求;

    nginx重发等情况;

    分布式RPC的try重发等;

    主要有 2 个部分:

    (1)前端用户操作

    (2)网络请求可能存在重试

    当然也不排除一些用户的恶意操作。

    问题

    就是同一份信息,重复的提交给服务器。

    场景

    1. 点击F5刷新页面: 当用户点击submit将已经写好的表单数据提交到服务器时,可以在浏览器的url看到地址和参数的变化,但因为网速等问题,用户当前页面并未刷新,或者点击刷新页面,造成表单重复提交。

    2. 重复点击提交按钮: 因为网络问题,未能及时跳转显示内容,部分用户可能会出于心急重复提交提交按钮,造成多次提交内容到服务器。

    3. 前进后退操作 :有些用户在进行某些工作操作时,可能出于需要或者某种情况,进行后退操作,浏览刚才填入的信息,在进行后退和前进的操作可能也会造成表单数据重复提交到服务器。

    4. 使用浏览器历史记录重复访问: 某些用户可能会出于好奇,利用浏览器的历史记录功能重复访问提交页面,同样会造成表单重复提交问题。

    解决思路

    前端

    方案一:禁用按钮提交

    设置标志位,提交之后禁止按钮。像一些短信验证码的按钮一般都会加一个前端的按钮禁用,毕竟发短信是需要钞票滴~

    ps: 以前写前端就用过这种方式。

    • 优点

    简单。基本可以防止重复点击提交按钮造成的重复提交问题。

    • 缺陷

    前进后退操作,或者F5刷新页面等问题并不能得到解决。

    最重要的一点,前端的代码只能防止不懂js的用户,如果碰到懂得js的编程人员,那js方法就没用了。

    方案二:设置HTTP报头

    设置HTTP报头,控制表单缓存,使得所控制的表单不缓存信息,这样用户就无法通过重复点击按钮去重复提交表单。

    <meta http-equiv="Cache-Control" content="no-cache, must-revalidate">

    但是这样做也有局限性,用户在提交页面点击刷新也会造成表单的重复提交。

    方案三:通过 PRG 设计模式

    用来防止F5刷新重复提交表单。

    PRG模式通过响应页面Header返回HTTP状态码进行页面跳转替代响应页面跳转过程。

    具体过程如下:

    客户端用POST方法请求服务器端数据变更,服务器对客户端发来的请求进行处理重定向到另一个结果页面上,客户端所有对页面的显示请求都用get方法告知服务器端,这样做,后退再前进或刷新的行为都发出的是get请求,不会对server产生任何数据更改的影响。

    这种方法实现起来相对比较简单,但此方法也不能防止所有情况。例如用户多次点击提交按钮;恶意用户避开客户端预防多次提交手段,进行重复提交请求;

    下面谈一谈后端的防止重复提交。

    后端

    幂等性

    如果是注册或存入数据库的操作,可以通过在数据库中字段设立唯一标识来解决,这样在进行数据库插入操作时,因为每次插入的数据都相同,数据库会拒绝写入。

    这样也避免了向数据库中写入垃圾数据的情况,同时也解决了表单重复提交问题。

    但是这种方法在业务逻辑上感觉是说不过去的,本来该有的逻辑,却因为数据库该有的设计隐藏了。

    而且这种方法也有一定的功能局限性,只适用于某系特定的插入操作。

    • 实现方式

    这种操作,都需要有一个唯一标识。数据库中做唯一索引约束,重复插入直接报错。

    • 缺点

    有很大的约束性。

    一般都是最后的一道防线,当请求走到数据库层的时候,一般已经消耗了较多的资源。

    直接加锁

    为了避免短时间的重复提交,直接使用加锁的方式。

    优点:不需要前端配合修改,纯后端。

    缺点:无法像 token 方法,准确的限定为单次。只能限制固定时间内的操作一次。

    个人理解:前端的方式依然是防君子不防小人。直接通过限制固定时间内无法操作,来限制重复提交。

    这个时间不能太长,也不能太短,一般建议为 10S 左右,根据自己的真实业务调整。

    锁也是同样的道理,token 其实也可以理解为一种特殊的锁。

    锁同样可以分为单机锁+分布式的锁。

     总结

    设置sql的字段唯一约束  这样就会报错

    设置前端点击之后弹出加载框 防止重复点击

    对方法加锁

  • 相关阅读:
    hdu 5224 Tom and paper 水题
    2015 UESTC 搜索专题N题 韩爷的梦 hash
    2015 UESTC 搜索专题M题 Palindromic String 马拉车算法
    2015 UESTC 搜索专题K题 秋实大哥の恋爱物语 kmp
    2015 UESTC 搜索专题J题 全都是秋实大哥 kmp
    2015 UESTC 搜索专题F题 Eight Puzzle 爆搜
    2015 UESTC 搜索专题E题 吴队长征婚 爆搜
    2015 UESTC 搜索专题D题 基爷的中位数 二分
    2015 UESTC 搜索专题C题 基爷与加法等式 爆搜DFS
    2015 UESTC 搜索专题B题 邱老师降临小行星 记忆化搜索
  • 原文地址:https://www.cnblogs.com/netlock/p/14246381.html
Copyright © 2011-2022 走看看