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

服务端防止重复提交

  •  
  •   wleexi · 85 天前 · 3684 次点击
    这是一个创建于 85 天前的主题,其中的信息可能已经有所发展或是发生改变。

    某个请求对应的是一个数据库的插入操作。从服务端角度来看,如何防止因为页面连续点击造成的重复提交。

    37 回复  |  直到 2018-11-26 11:46:38 +08:00
        1
    leriou   85 天前   ♥ 1
    csrf , 或者自己用事件 id 去重
        2
    utoyuri   85 天前   ♥ 5
    根据 request 内容生成一个 unique key 塞到 redis,结束后删掉。接到新 request 后在 redis 里面找一下,存在就丢弃这个 request。
        3
    lihongjie0209   85 天前
    @leriou 跨站请求伪造 和 服务端有什么关系?
        4
    t6attack   85 天前
    参考眼前的页面。
    <input type="hidden" value="xxxxx" name="once">
        5
    wleexi   85 天前
    @t6attack
    @leriou

    前端保持不变的情况下,单靠服务端来处理有什么办法么。
        6
    wleexi   85 天前
    @utoyuri 类似生成 md5 这种么。
        7
    Sharuru   85 天前 via Android
    PRG
        8
    allanzhuo   85 天前 via Android
    token
        9
    jugelizi   85 天前
    就是表单 token 啊 如果不是前后端分离的话
        10
    leriou   85 天前   ♥ 1
    @wleexi 其实就是你需要能识别出来相同的请求, 做幂等处理, csrf 的原理是你每次前端的表单页面生成时候提供一个唯一的 csrf_id, 发起请求的时候这个 id 会跟着一起到达后端,标记本次请求, 如果后端发现这个 id 已经处理过一次了, 就说这次请求就是没有刷新页面情况下的重复的提交
        11
    wleexi   85 天前
    @jugelizi
    @allanzhuo

    有考虑过提交完成后把信息塞到 cookie 里,下一次提交如果 cookie 里发现有就不做插入。
    如果提交是异步,前一次请求每完成,接着提交了第二次。。。也不能解决这个问题
        12
    godoway   85 天前 via Android
    @jugelizi 那么如果前后端分离怎么防止重复提交。
        13
    lihongjie0209   85 天前
    @leriou 前端保持不变的情况下 这个办法不可行, 你要改表单的逻辑
        14
    allanzhuo   85 天前 via Android
    @wleexi 我之前瞎写的,你可以参考下 https://www.cnblogs.com/laoyeye/p/9557269.html
        15
    allanzhuo   85 天前 via Android
    @allanzhuo 之前瞎写的一点思考,可以参考下
        16
    wleexi   85 天前
    @leriou 就是说还需要搞个地方存这个 id 对么。
        17
    allanzhuo   85 天前 via Android
    @wleexi 提交表单前先请求 token,提交的时候吧 token 带着,当个参数。
        18
    wleexi   85 天前
    @allanzhuo 意思懂,这样前端也要参与到改造中了,文章我看下,thx。
        19
    wleexi   85 天前
    @allanzhuo 如果塞到 cookie 里不就好了 ,就是刚才说的异步那个问题,
        20
    iyangyuan   85 天前 via iPhone
    直接把 token 放 cookie 里不就行了?
        21
    checgg   85 天前   ♥ 1
    这个问题的实际需求是什么?
    1 防止提交两次?
    这只能客户端去解决。

    2 防止数据入库两次?
    那么重复提交的定义是什么?
    两个客户端,提交同一份数据,算重复提交吗?
    如果算,设置数据库唯一索引就好,写入相同数据会失败。
    如果不算,服务端没法验证。因为客户端请求都可以伪造。
        22
    dagger   85 天前
    你都说了是为了防止页面连续点击,那不去改前端的话,后端真的只能靠意念来感知了,就像前阵子那个要感知手机壳颜色一样
        23
    utoyuri   85 天前
    @wleexi 可以的 甚至明文都可以 只要唯一
        24
    reself   85 天前 via Android
    @wleexi 可以把 csrf ——这个场景也可以称为 token ——放到 header 里,就不用改表单了
        25
    TangMonk   85 天前 via Android
    @lihongjie0209

    跨站请求伪造的 token 需要服务端来验证
        26
    reself   85 天前 via Android
    @lihongjie0209 本质是 token,只是顺带具有 csrf 的功能,表单只是实现方式,放表单,放 session,放 header,放 meta 都可以
        27
    TangMonk   85 天前 via Android
    可以用类似 csrf 的 token,并且在表单在提交了后 disable 掉
        28
    TangMonk   85 天前 via Android
    可以用类似 csrf 的 token,并且在表单在提交了后把体检按钮 disable 掉
        29
    TangMonk   85 天前 via Android
    体检按钮☞提交按钮
        30
    Vegetable   85 天前 via Android
    总之就是需要一个事务 id。csrf 的 token 功能和这个需求有一定的交叉,可以使用但是不完全匹配。
    重复提交你说是连续点击,那么做个限速就好了,后几秒的请求丢弃就完了,用到缓存或者 session。这种需求前端配合禁用提交按钮好一点。
        31
    paicha   85 天前
    这是业务问题。
        32
    showecho   85 天前
    通常我是改前端,点击之后马上变为 disabled,这样就无法再次提交了,后端通常也有判断的逻辑,比如评论的话看时间间隔,注册的话比如邮箱唯一等;

    这应该就可以解决了吧?
        33
    akira   85 天前
    @utoyuri 做个 3s 自动过期就好了,逻辑还简单点
        34
    utoyuri   85 天前
    @akira 很多个同样请求同时过来的时候 3s 过期时间就歇菜了
        35
    utoyuri   85 天前
    @akira 忽略我上一条弱智回复
        36
    yc8332   85 天前
    表单 token 或者是 session 控制,还有同一个用户的提交数据 sha1 一下,缓存个几秒(这个相当于加锁)。。。
        37
    Raymon111111   84 天前
    前端让按钮只能点一下是最好的

    后端防恶意请求可以用 锁+数据库查询 的方法搞定幂等
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   3805 人在线   最高记录 4346   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 17ms · UTC 01:28 · PVG 09:28 · LAX 17:28 · JFK 20:28
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1