V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
guyskk
V2EX  ›  Python

设计无状态验证码,大家看下是否可行,有没有什么漏洞?

  •  
  •   guyskk ·
    guyskk · 2016-03-30 11:49:05 +08:00 · 7929 次点击
    这是一个创建于 3185 天前的主题,其中的信息可能已经有所发展或是发生改变。

    无状态验证码不需要在 SESSION 中保存数据,流程如下:

    1. 服务端先配置一个密钥 KEY
    2. 客户端请求验证码 TOKEN, 服务端生成一个随机字符串 TEXT ,再生成一个 SALT ,用 KEY 和 SALT 对 TEXT 进行加密 加密后的 TEXT 和 SALT 拼接到一起,作为 TOKEN 返回给客户端
    3. 客户端请求验证码图片,携带验证码 TOKEN, 服务端根据 KEY 和 TOKEN 中的 SALT ,解密出 TEXT ,用这个 TEXT 生成一幅图片
    4. 客户端发送业务请求,携带验证码 TOKEN 和用户输入的 CODE, 服务端根据 KEY 和 TOKEN 中的 SALT ,解密出 TEXT ,和 CODE 比对

    代码 https://github.com/guyskk/kkblog/blob/master/kkblog/captcha.py

    大家看下是否可行,有没有什么漏洞?

    31 条回复    2016-06-23 13:18:38 +08:00
    jedyu
        1
    jedyu  
       2016-03-30 11:55:03 +08:00
    把 Session 中的数据挪到了 Token 中而已
    cxh116
        2
    cxh116  
       2016-03-30 11:56:39 +08:00
    你要明白 session 的 id 不过是存在 cookie 里面的一个 token 而已.
    guyskk
        3
    guyskk  
    OP
       2016-03-30 11:58:05 +08:00
    @jedyu 是的,这样服务器就不需要保存 Session ,客户端也可以不用 Cookie
    Archangel_SDY
        4
    Archangel_SDY  
       2016-03-30 11:59:08 +08:00   ❤️ 4
    这个验证码没有有效期,并且可以多次使用? 那我始终拿一组 Token 和 Code 去刷就可以了呗.
    loading
        5
    loading  
       2016-03-30 12:01:01 +08:00 via Android
    jugelizi
        6
    jugelizi  
       2016-03-30 12:04:17 +08:00   ❤️ 1
    哈后 4L 一脚踢坏了楼主的轮子
    guyskk
        7
    guyskk  
    OP
       2016-03-30 12:06:53 +08:00
    @Archangel_SDY 确实是。在第 2 步中,随机字符串 TEXT 后面再加上有效期应该可以。验证码在有效期内可以重复使用。
    ybdhjeak
        8
    ybdhjeak  
       2016-03-30 12:10:13 +08:00
    直接把 code 加密写进 cookie 不就行了,下次让客户端带着 cookie 和验证码一起来
    guyskk
        9
    guyskk  
    OP
       2016-03-30 12:11:40 +08:00
    @guyskk 有效期 1~3 分钟
    ybdhjeak
        10
    ybdhjeak  
       2016-03-30 12:12:11 +08:00
    你的 token 和 cookie 没啥区别吧,只不过是传递方式不同, session id 也可以用参数形式传递啊
    gy911201
        11
    gy911201  
       2016-03-30 12:14:17 +08:00   ❤️ 1
    @guyskk 不加仅能使用一次的限制,验证码就形同虚设,对于暴力提交请求的程序来说, 1 分钟识别一次验证码相当于没有验证码
    keller
        12
    keller  
       2016-03-30 12:17:14 +08:00
    有效期内这个验证码不就可以无限使用啊?
    ty0716
        13
    ty0716  
       2016-03-30 12:18:09 +08:00
    应该携带一个应用的 id,有效时间是多少,当下次刷新时,自动将该应用 id 的验证码删掉,
    反正就是要保证验证码只能用一次。 不然还叫什么验证码
    dndx
        14
    dndx  
       2016-03-30 12:20:55 +08:00
    目测有效期内可以重放,对机器人来说还是很方便的。
    knightdf
        15
    knightdf  
       2016-03-30 13:03:13 +08:00
    这不是一次性的验证码。。。
    menc
        16
    menc  
       2016-03-30 13:25:33 +08:00
    没有漏洞,而且是业界一直在采用的方案。。
    不过业界把这个东西叫做 csrf token ,因为这样一次性的 token 可以防止 csrf 攻击,
    事实上,如果 token 用后即扔的话,用不着对 token 这么大张旗鼓的做手脚
    knightdf
        17
    knightdf  
       2016-03-30 13:30:01 +08:00
    @menc 大哥,你是混哪个业界的?好屌
    flowfire
        18
    flowfire  
       2016-03-30 14:22:46 +08:00
    何必呢。。。
    cheneydog
        19
    cheneydog  
       2016-03-30 14:42:48 +08:00
    1. 服务端的密钥 KEY 是全局的所有用户所有请求都一样
    2. 加密后的 TEXT 和 SALT 拼接到一起返回,相当于暴漏了 SALT
    有一定的被猜解的可能性。


    也不觉得比加密后写入 cookie 有什么优势。
    wlsnx
        20
    wlsnx  
       2016-03-30 14:58:16 +08:00
    有点奇怪,为了避免保存数据,所以每次都生成新数据,逻辑更复杂了。
    qiyuey
        21
    qiyuey  
       2016-03-30 16:18:33 +08:00
    你只是做了一个简化版的 session
    shade
        22
    shade  
       2016-03-30 18:44:33 +08:00
    OAuth 也是这样的吧
    cevincheung
        23
    cevincheung  
       2016-03-30 18:47:15 +08:00
    @wlsnx web 集群解决 session 一致性
    Abirdcfly
        24
    Abirdcfly  
       2016-03-30 19:29:18 +08:00 via iPhone
    @knightdf 我觉得他说的没错啊。默认是 cookie 来做这些事情。有的禁止 cookies ,不就用的是这个方案?
    zwzmzd
        25
    zwzmzd  
       2016-03-30 19:39:37 +08:00   ❤️ 1
    ddou
        26
    ddou  
       2016-03-30 20:08:06 +08:00
    @zwzmzd 内容不错,非常感谢。
    shade
        27
    shade  
       2016-03-31 13:19:59 +08:00
    webhook 是什么?
    guyskk
        28
    guyskk  
    OP
       2016-03-31 16:04:05 +08:00
    @shade kkblog 代码里面的吗,那个是 github 的开放接口
    playsoso
        29
    playsoso  
       2016-06-23 11:26:17 +08:00
    我觉得可以使用 jwe 方案 ,也就是 jwt 其中客户端内容加密过 , 请求验证码同时 发放 token , 提交验证码时携带 token
    通过 token 里 签发时间和过期时间来判断是否有效 , token 内容与验证码结果做比对
    playsoso
        30
    playsoso  
       2016-06-23 13:01:33 +08:00
    @playsoso 因为涉及到重放攻击,而且验证码有状态 服务端需要记录是否发放过验证码 和 验证码是否已验证过,所以还是需要依赖服务端 状态保存
    guyskk
        31
    guyskk  
    OP
       2016-06-23 13:18:38 +08:00 via Android
    @playsoso 要保证验证码只能用一次,服务端必需要有状态,所以无解。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3033 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 82ms · UTC 14:04 · PVG 22:04 · LAX 06:04 · JFK 09:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.