V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
awesomelei
V2EX  ›  程序员

如何防止表单重复提交?

  •  
  •   awesomelei · 2020-01-07 10:31:27 +08:00 · 5326 次点击
    这是一个创建于 1789 天前的主题,其中的信息可能已经有所发展或是发生改变。

    用 CSRF 吗? 能否说下细节,

    25 条回复    2020-01-09 14:55:11 +08:00
    hsk9044
        1
    hsk9044  
       2020-01-07 10:56:01 +08:00
    当然是用反 CSRF 来实现了, 不仅可以从业务上防止表单重复提交, 也可以从安全上禁止 CSRF 漏洞.
    不同的语言框架应该都有类型的拓展, 你应该先搜索一下.
    大概的原理其实就是每个页面都生成一个 token 到前端, 并且也把 token 带到 session 上, 表单提交时把 token 也一起提交到后端, 后端做一下匹配判断是否相同就可以了
    Dcynsd
        2
    Dcynsd  
       2020-01-07 10:58:15 +08:00
    前端也可以先做下防重复点击,点击提交表单后,按钮 disabled
    kop1989
        3
    kop1989  
       2020-01-07 11:00:19 +08:00
    后端的话就是利用唯一码,一个码只能提交一次表单。
    前端的话就是按钮复点检查,一旦点击,在不满足特定条件的情况下按钮监听锁死
    learnshare
        4
    learnshare  
       2020-01-07 11:03:29 +08:00
    前端锁定提交按钮只是一种防君子的操作,F12 就可以轻松绕过
    楼上的唯一码是个不错的选择
    murmur
        5
    murmur  
       2020-01-07 11:05:07 +08:00
    带 token 就行,token 是动态的,获取表单的时候唯一
    xuanbg
        6
    xuanbg  
       2020-01-07 11:08:47 +08:00
    前端按钮防抖,然后后端两个方案,
    1、对每个来源的接口调用进行限制,使其在单位时间内(譬如 3 秒)只能调用一次。这个方案不需要预先调用接口获取 token,只需要在网关上面实现即可,无需前端配合。
    2、进入提交数据的页面先调用接口获取 token,提交数据的时候限制每个 token 只能使用一次。这个方案更保险,但需要多调用一次接口,需要前端配合。
    yamedie
        7
    yamedie  
       2020-01-07 11:11:37 +08:00
    强制所有 post 请求必须带业务流水号, 后端判重. 能防止反向代理的超时重发或者重放攻击, 不能防前端页面重复点击
    manami
        8
    manami  
       2020-01-07 11:13:16 +08:00 via Android
    验证码 /token 方案
    hantsy
        9
    hantsy  
       2020-01-07 12:27:53 +08:00
    CSRF 在很多 Web 框架中内置了,生成 Form 或者 Request 时添加一个唯一 CSRF Token。
    Spring Security 类似的安全框架也有 CSRF 验证功能。
    opengps
        10
    opengps  
       2020-01-07 12:35:02 +08:00
    幂等性,提交不要紧,只要 requestId 相同做后端做相同的返回就行了
    wangyzj
        11
    wangyzj  
       2020-01-07 12:39:39 +08:00
    CSRF
    pandait
        12
    pandait  
       2020-01-07 12:53:02 +08:00
    这种别想了。就直接 CSRF 解决就好了。CSRF 这个还要说细节? 搜索引擎可以帮助您。
    lihongjie0209
        13
    lihongjie0209  
       2020-01-07 12:57:26 +08:00
    @opengps #10 那是不是意味着要把每一个 requestId 的结果都存储起来, 不然后端怎么做相同返回
    opengps
        14
    opengps  
       2020-01-07 13:08:52 +08:00
    @lihongjie0209 用短暂缓存拦截重复提交,重复提交的返回结果就是缓存内容
    lihongjie0209
        15
    lihongjie0209  
       2020-01-07 13:10:46 +08:00
    @opengps #14 requestId 怎么生成
    opengps
        16
    opengps  
       2020-01-07 13:18:38 +08:00
    @lihongjie0209 前端控制即可(接口不返回成功,不重新生成),或者是后端完成业务再生成返回
    以前写过一点,不太完善: https://www.opengps.cn/Blog/View.aspx?id=426
    violetlai
        17
    violetlai  
       2020-01-07 13:23:07 +08:00
    后端查重不就好了
    seanpan
        18
    seanpan  
       2020-01-07 15:39:52 +08:00
    用表单令牌
    seanpan
        19
    seanpan  
       2020-01-07 15:41:20 +08:00
    @violetlai 他指的应该是防止同一条数据重复插入数据库的情况,直接在插入数据表前拦截比较好把?
    IMCA1024
        20
    IMCA1024  
       2020-01-07 15:43:41 +08:00
    防重复 token
    IMCA1024
        21
    IMCA1024  
       2020-01-07 15:46:50 +08:00
    进入表单(数据)页面提前向后端获取一个 token
    (后端将这 token 写入 redis 或其他地方,然后返回给前端)

    提交表单(数据) 需要带上 token

    后端首先判断该 token 存不存在,存在,删除该 token 然后进入 后续业务逻辑
    ncwtf
        22
    ncwtf  
       2020-01-07 16:07:57 +08:00
    哼,动态接口,比如:第一次接口是 getuser10086、第二次就是 getuser10010。让敌人察觉不到规律。接口每收到一次请求,马上废弃接口。万无一失。
    yunye
        23
    yunye  
       2020-01-07 16:15:41 +08:00 via Android   ❤️ 1
    凭街道证明和单位介绍信提交表单
    chibupang
        24
    chibupang  
       2020-01-07 16:20:48 +08:00 via iPhone
    根据表单内容计算特征码,用 redis 做特征码缓存,设置失效时间。
    fengmumu
        25
    fengmumu  
       2020-01-09 14:55:11 +08:00
    你这个要问防止用户意外多次提交?还是防止有人恶意多次提交
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2818 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 08:59 · PVG 16:59 · LAX 00:59 · JFK 03:59
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.