V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
51300520
V2EX  ›  信息安全

卧槽, jwt 这种认证方式竟然不需要在服务器本地存信息?

  •  
  •   51300520 · 2019-07-06 03:43:58 +08:00 · 9230 次点击
    这是一个创建于 1977 天前的主题,其中的信息可能已经有所发展或是发生改变。

    以往我登录验证一直是生成 token,发给客户端,自己存数据库,下次客户端发来我从数据库里面取出对比。

    刚调试一个 golang 的登录程序,我就纳闷,他生成一个 token 返回给客户端,我重启服务程序后该 token 竟然还能准确认证。该 token 我并没有在服务器上落地,重启后它是怎么还能继续验证的? 我以为是不是 jwt 包在哪里偷偷落地了,于是单步仔细检查了一番,发现没有。 于是 google,竟然发现这玩意不需要落地就就能一直验证。 太TM神奇了。。。。

    顺便问句,这玩意可靠吗?容易被破解不?如果可靠,那以后登录验证就用它了

    31 条回复    2019-07-07 19:47:11 +08:00
    geelaw
        1
    geelaw  
       2019-07-06 04:05:10 +08:00 via iPhone
    JWT 是数字签名,所以只需要 public key 和受信任的时间即可验证有效性
    yamedie
        2
    yamedie  
       2019-07-06 06:16:58 +08:00 via Android
    服务端不存库的话,无法解决单设备单点登录,另外还有 token 被盗用的问题。楼下讲讲如何魔改解决这俩问题?
    yamedie
        3
    yamedie  
       2019-07-06 06:21:12 +08:00 via Android
    关于 token 被盗用,忽然想到也许可以把设备的一部分特征放进 payload 里,比如 ua ?但那样会导致 token 变得巨长。。。
    yamedie
        4
    yamedie  
       2019-07-06 06:25:17 +08:00 via Android
    @yamedie 自问自答:也许可以把 ua 散列成摘要后,取几位,作为一个更短的设备特征摘要,放进 payload。缺点是加重服务端验证时的 cpu 负载
    iBenlim
        5
    iBenlim  
       2019-07-06 06:43:54 +08:00 via Android
    而且居然还可以在 Token 中存 UserId …
    mcfog
        6
    mcfog  
       2019-07-06 06:44:45 +08:00 via Android
    不建议 jwt 做一般业务的会话认证

    详情 http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
    virusdefender
        7
    virusdefender  
       2019-07-06 07:29:20 +08:00
    你会发现很多 jwt 的实现都没有改密码之后失效老 token 的功能,只能自己再包装下
    lhx2008
        8
    lhx2008  
       2019-07-06 07:45:06 +08:00 via Android   ❤️ 3
    简单业务,对安全没有要求可用。
    缺点不少,一个是加解密费时间,一个是 jwt 格式改了之后,后端适配很烦,一个是服务器不好做黑名单,改密码之后,jwt 仍然是有效的,必须建立一个 k-v 的黑名单,那么问题来了,已经建了这个名单,和直接存个用户 Object 有啥区别
    keepeye
        9
    keepeye  
       2019-07-06 09:22:50 +08:00
    我们正考虑不再使用 jwt,最大的原因是没法清除单个会话
    dodo2012
        10
    dodo2012  
       2019-07-06 09:24:08 +08:00
    不使用 jwt 的话,现在有啥更合适的
    hst001
        11
    hst001  
       2019-07-06 09:29:33 +08:00 via Android
    jwt 有 jwt 的问题,当时考察了一番,决定不使用,纯添麻烦。
    sparrww
        12
    sparrww  
       2019-07-06 09:42:41 +08:00
    @lhx2008 改密码的问题,生成 token 的时候把密码作为加密的一部分是可以解决的
    geelaw
        13
    geelaw  
       2019-07-06 10:02:01 +08:00 via iPhone
    @lhx2008 #8 可以给用户存一个 version number,在用户变更安全信息或者撤销所有会话的时候增加之,只有 version number 足够高的签名才有效就行了。

    @keepeye #9 赞同。

    (如果引入 state 的话 JWT 就属于传统 session 的特例了)
    laoyur
        14
    laoyur  
       2019-07-06 10:49:53 +08:00
    所以楼主的心情是:
    我擦,发现新大陆,这么好用的东东,赶紧去 v2 找认同 --> 一堆人劝退 --> 我勒个去,白高兴一场
    honeycomb
        15
    honeycomb  
       2019-07-06 10:59:55 +08:00 via Android
    @lhx2008 可以用 bloom filter 作黑名单,空间要求比 k-v 小
    MonoLogueChi
        16
    MonoLogueChi  
       2019-07-06 11:05:55 +08:00 via Android
    jwt 好像是根据密钥和时间戳验证的,只要有密钥能用,每到过期时间,就一直可以用
    loading
        17
    loading  
       2019-07-06 12:36:08 +08:00 via Android
    jwt 那串东西分三部分,前两部分都是可公开的东西,里面有 uid 什么的,最重要是有这个 token 的过期时间(这是实际时间,验证的时候是你服务器的时间,所以没有时空问题),然后这些信息 base64 了一下。

    那么如何防止别人伪造呢?

    第三段就是保证。服务器收到前两段,然后加入一个自定义的固定字符串(slat),然后用私钥加密,得到第三段。

    只要拿到这一段字符,基本就可以为所欲为,只要没超期。

    为了拦截一个已知已经被泄露的 token,jwt 里面很多时候就又会加上一个对应的 keyid,而这个 keyid 又需要在服务器进行保持,走回了老路。

    jwt 是一种轻量的登录方式,因为没魔改的话不需要跑数据,只需要加解密计算,这就不会遇到数据库瓶颈了,对不是苛刻安全要求高并发非常合适。

    没有银弹,看场合。
    jedrek
        18
    jedrek  
       2019-07-06 12:39:00 +08:00
    51300520
        19
    51300520  
    OP
       2019-07-06 13:20:47 +08:00
    这个东西好像很适合网站啊,网站一般允许多点登录
    51300520
        20
    51300520  
    OP
       2019-07-06 13:21:03 +08:00
    @laoyur
    哈哈哈哈哈哈
    AlphaTr
        21
    AlphaTr  
       2019-07-06 13:27:32 +08:00 via iPhone
    单点登录的话,用非对称加密,业务方用公钥验证签名就行,私钥保存在认证服务器;黑名单这种要求不严格的话,定期去认证服务器拉黑名单列表就行
    dcalsky
        22
    dcalsky  
       2019-07-06 14:08:05 +08:00 via Android
    @yamedie token 放 header 里再上 ssl。如果这也能丢了那密码也能丢。主流做法是在后端存 refresh token 来刷新 access token (上文的 token )。这样能防止丢失 access token 被长期使用。
    Zzdex
        23
    Zzdex  
       2019-07-06 14:08:13 +08:00 via iPhone
    .........
    limuyan44
        24
    limuyan44  
       2019-07-06 14:48:02 +08:00
    https://jwt.io/introduction/ 看完对 jwt 就没那么多疑问了,jwt 本身的实现是很简陋的,如果使用 jwt 根据具体的场景更多是配合其他的策略,毕竟说白了 jwt 只是解决了数据信任的问题。
    chinvo
        25
    chinvo  
       2019-07-06 15:59:52 +08:00 via iPhone
    jwt 的 payload 放一个服务器生成的字符串,验证时额外增加对 payload 的验证,“吊销”这个字符串就能达成“吊销” jwt 的目的
    loading
        26
    loading  
       2019-07-06 16:23:52 +08:00 via Android
    @chinvo 既然服务器都已经要存 playload 了,不如退回去 session 方式。
    cheneydog
        27
    cheneydog  
       2019-07-06 16:43:23 +08:00
    有好处也有坏处,淡定。
    yamedie
        28
    yamedie  
       2019-07-06 16:52:00 +08:00 via Android
    @loading 在服务器水平扩展时需要多个服务器之间会话保持来共享 session,我个人感觉这种技术是很过时的
    loading
        29
    loading  
       2019-07-06 17:36:45 +08:00 via Android
    @yamedie 所以我说没有银弹,jwt 如果安全问题需要考虑,例如要屏蔽某个 token,那么就要增加标记,然后就会遇到 session 的共享问题。
    mingmeng
        30
    mingmeng  
       2019-07-07 00:09:48 +08:00 via Android
    jwt 好处是很轻,但是实际对于业务安全来说还是要做很多包装的~
    danmu17
        31
    danmu17  
       2019-07-07 19:47:11 +08:00
    用 jwt 做 session token 属于安全漏洞的范畴了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1035 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 20:52 · PVG 04:52 · LAX 12:52 · JFK 15:52
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.