V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
bayker
V2EX  ›  前端开发

前后端分离, JWT 还是 Oauth2?

  •  1
     
  •   bayker · 2018-03-20 10:19:30 +08:00 · 27058 次点击
    这是一个创建于 2444 天前的主题,其中的信息可能已经有所发展或是发生改变。

    自己内部的一套系统,不存在提供第三方调用。

    采用前后端分离, 使用 JWT 还是 oauth2?

    第一次使用,不是太明白,JWT 怎么实现 token 刷新,token 过期,后端禁用?

    25 条回复    2018-03-20 16:07:40 +08:00
    EPr2hh6LADQWqRVH
        1
    EPr2hh6LADQWqRVH  
       2018-03-20 10:38:43 +08:00
    没法过期,参考证书的 CRL 机制。
    EPr2hh6LADQWqRVH
        2
    EPr2hh6LADQWqRVH  
       2018-03-20 10:39:40 +08:00
    不是没法过期,是没法提前禁用,嗯,就是你说的后端禁用
    bolide2005
        3
    bolide2005  
       2018-03-20 10:46:24 +08:00   ❤️ 1
    这两个就不是一个应用场景,理论上来说你可以都用,用户登录使用 oauth2,给用户邮箱发送验证链接用 jwt
    jwt 的设计中包含了 expire time,方案是放在 jwt 的 payload 中; token 刷新预留一个 path 就 ok 了,访问这个 path,提取并验证用户信息后发一个新的 token 返回给客户端;后端禁用在 jwt 的设计中是不能实现的,当然你可以在数据库里保存 token 并标记,但这违反了 jwt 的设计原则,要真是有这样的需求,说明你的使用场景不适合 jwt
    ycz0926
        4
    ycz0926  
       2018-03-20 10:53:29 +08:00
    oauth2
    方便后续接入其他系统
    ycz0926
        5
    ycz0926  
       2018-03-20 10:53:56 +08:00
    @ycz0926 结合 sso
    mdluo
        6
    mdluo  
       2018-03-20 10:57:39 +08:00
    你可能并不需要 OAuth2: https://git.io/vxGxy
    notreami
        7
    notreami  
       2018-03-20 12:24:18 +08:00
    根据你的项目,直接一个唯一 id,生成 token,每次请求都去校验下这个 token 就可以了。
    brelian
        8
    brelian  
       2018-03-20 13:15:09 +08:00 via Android
    如果 token 要刷新不建议用 JWT,验证登录态后每次都需要重新颁发 token 吧。
    feverzsj
        9
    feverzsj  
       2018-03-20 13:17:05 +08:00
    session id 是最好的
    javlib
        10
    javlib  
       2018-03-20 13:40:48 +08:00
    我感觉 JWT 的好处是不需要在服务端存储用户 token,这个更适合给程序调用使用,比如临时获取一个 JWT,过期时间是 1 个小时,过期后重新获取。
    JWT 给用户用不是很合适,如果你需要这些功能
    1 对 token 刷新使用期限
    2 支持 token 失效
    JWT 就不好用了。
    bayker
        11
    bayker  
    OP
       2018-03-20 13:51:59 +08:00
    感谢大家回复,
    请问
    @avastms
    @brelian
    那怎么实现像 session 20 分钟未向服务端请求就过期呢?比如登陆了管理系统后台,如果一直没过期,就存在不安全啊?
    @javlib
    是否使用 oauth2 能实现?
    nl101531
        12
    nl101531  
       2018-03-20 13:54:21 +08:00 via Android
    @bolide2005 可以下发 token 的时候保存用户版本,然后改密码用户版本自增。实现吊销功能。
    mdluo
        13
    mdluo  
       2018-03-20 13:54:34 +08:00
    很明显这种没有第三方参与的场景是不适合用 OAuth 的,参考我上面 #6 的回复的链接

    JWT 的过期和刷新也很好做,参考业界主流做法,AWS、Azure 和 Auth0 都是用 JWT 为载体,ID Token + Access Token + Refresh Token 的模式:

    https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-using-tokens-with-identity-providers.html

    https://docs.microsoft.com/en-us/azure/active-directory/develop/active-directory-token-and-claims

    https://auth0.com/docs/tokens
    phpcxy
        14
    phpcxy  
       2018-03-20 13:59:41 +08:00
    jwt 除了后端禁用外其他都可以实现到
    bayker
        15
    bayker  
    OP
       2018-03-20 14:04:43 +08:00
    @phpcxy 需求是 只要有持续与服务器交互,过期时间都会往后延续,除非间隔了 20 分钟都未交互,token 就过期。
    或者在另一台电脑修改了密码,以前登陆的地方都失效?
    bayker
        16
    bayker  
    OP
       2018-03-20 14:07:27 +08:00
    @bolide2005 感谢,明白了 jwt 的使用场景?意思是 jwt 不适合做用户鉴定? 但 oauth2 感觉在自己内部系统间使用好像也不适合?
    bayker
        17
    bayker  
    OP
       2018-03-20 14:19:50 +08:00
    @mdluo 能给一个 ID Token + Access Token + Refresh Token 的文章吗? 明白了不适合 oauth2 但没明白 jwt 的解决方案。
    whypool
        18
    whypool  
       2018-03-20 14:38:40 +08:00
    jwt 就行,现在都玩微服务,可以很好和其他服务互相配合
    一套 jwt 机制,配合现在多客户端(web,android,ios,weixin),基本上可以做到无缝切换
    bayker
        19
    bayker  
    OP
       2018-03-20 14:41:06 +08:00
    @whypool 请问 jwt #15 楼的需求怎么实现呢? 后端用数据库记录 需要过期的 token?
    whypool
        20
    whypool  
       2018-03-20 14:49:56 +08:00
    @bayker jwt 一般不存数据库,而是放缓存,比如 reids
    如果有交互就重置一下有效期就行,或者自己写个对比一下时间戳
    phpcxy
        21
    phpcxy  
       2018-03-20 15:01:25 +08:00
    @bayker #19
    设置一个刷新有效期,在有效期内的访问都刷新一下 token 返回新 token 给客户端;
    后台作废 token 的话就利用缓存记录一个本 ID 的 token 作废时间,在作废时间以前颁发的 token 失效(前提是你的 token 有记录颁发时间~)
    bolide2005
        22
    bolide2005  
       2018-03-20 15:26:01 +08:00   ❤️ 2
    @nl101531 #12 可以,是一种解决的思路,但我倾向于不使用这种方法,至少不作为设计阶段的方案使用,很大程度上 token 的作用就是为了在请求量比较大且多终端复用的情况下,减少登录和用户数据查询操作产生的数据库压力,如果每次还需要检查 token 版本,不如直接用最基本的 session 来实现;修改密码需要多终端下线的操作,可以通过向终端发送重新登录的通知来实现,如果担心之前的 token 没作废产生的安全风险,应该把在敏感场景中排除 token 的效力。比如,正常的查询操作都可以使用 token,是不会触发重新登录的操作的,但如果涉及到财产、敏感信息的查询和操作,都应该进行重新登录并用 session 维护登录信息。token 永远不是安全性高的解决方案。token 也不是为了这种场景存在的。


    @bayker #15 我上面举的例子应该能回答这个问题:token 用于频繁且不敏感的操作。
    timonwong
        23
    timonwong  
       2018-03-20 15:34:08 +08:00
    先打消一下误解,比如 JWT 的 revocation
    1. JWT 有 jti claim,用作唯一 id 时候,可以做 blacklist 来 revocation,当然按照传统的方式 whitelist 也是可行的;
    2. group revocation: 同理,加入一个自定义的 claim,比如 audit_ids,可以按照 blacklist 的方式作分级 revocation ;
    为了让 blacklist 大小可控,一般不允许不 expire 的 JWT token。

    但是,请不要将 JWT 作为 session 来使用。

    如果你需要一个全功能的,请看基于 OAuth2 和 JWT 的 openid connect
    banks0913
        24
    banks0913  
       2018-03-20 15:40:57 +08:00
    如果不用 session,用 jwt 又没法在后端禁用或者失效,有什么简单通用的解决方案吗?
    nl101531
        25
    nl101531  
       2018-03-20 16:07:40 +08:00 via Android
    @bolide2005 嗯,想要实现吊销的话就必须要存。其实版本这个东西可以存在 redis,内存占用很小的。具体还要看公司的业务来定。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3264 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 12:26 · PVG 20:26 · LAX 04:26 · JFK 07:26
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.