请教各位一个问题, 为什么 session 机制没有被 JWT 所取代? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
httpbin - 协议调试工具
httpstatuses - 协议状态码查询
httpie - cURL-like tool for humans
Fiddler
baiyi
V2EX    HTTP

请教各位一个问题, 为什么 session 机制没有被 JWT 所取代?

  •  
  •   baiyi 2017-08-10 17:57:43 +08:00 16828 次点击
    这是一个创建于 2984 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在细读 REST 那篇论文, HTTP 的设计应该就是来自于这里

    看到了 无状态 这里, 有一点小疑问: 为什么 session 机制没有被 JWT 所取代?

    session 毫无疑问是不符合无状态的, 它使得会话状态(session state)保存在了服务器中. 产生的问题也很清晰: 由于会话状态保存在了服务器, 所以需要多个服务器间同步会话状态

    JWT 就是将会话状态存在了客户端(cookie), 服务器端需要的时候自然会解析验证. 也没有多服务器间的同步麻烦.

    但是, 现状却是大多网站都是 session 的机制, JWT 只有小部分的 WEB API 使用.

    第 1 条附言    2017-08-11 09:49:34 +08:00

    我的标题可能起的有些问题, 我想请教的是 Session ID & JWT

    会话状态(session)在交互型的网站是无法避免的, 但是 Session ID 在之前我看来是可以避免的

    在我的理解里

    Session ID 是使用随机字符串, 会话状态内容是保存在服务器端的

    而 JWT 的本质是校验, 他得到的会话状态完全来自于客户端, 没有存储在服务器, 这在我看来完全是符合无状态架构的.

    至于说过期, 注销等问题也有想过一些解决方案.

    不过, 经过讨论和V友们的指点, 我也明白了:

    每次请求的内容过多是无状态的缺点, 但是这个缺点也不应该无限制的放大, cookie 的4096字节的限制应该就是做出的这种限制.

    那一旦 jwt 所需要存储的内容超过了某个阈值, 它的某些内容需要使用 ID 等标识, 其实与 Session ID 就没有太大的区别了.

    虽然之前我一厢情愿的想着 jwt 中的 id 代表资源标识, 但是其实本质上没有区别.

    so, 这其实是一个比重取舍的问题, 会话状态需要存储的东西越多, 越不应该使用 jwt , 因为 jwt 要比 Session ID这个随机字符串大多了

    第 2 条附言    2017-08-11 10:00:45 +08:00

    万分感谢V友的热心指点!!!

    同时希望这些内容对收藏的朋友有所帮助

    第 3 条附言    2017-09-05 16:29:48 +08:00
    《 RESTful Web APIs 》对于 Cookies 中 Session 机制 的看法与我一致, 破坏了架构约束~
    第 4 条附言    2017-09-05 16:38:50 +08:00
    《 RESTful Web APIs 》 中提出了 Cookies 限制了 HTTP 请求的内容. 使得之后的请求中必须要带有 Cookie 信息, 同样违反 [无状态] 约束
    99 条回复    2021-03-07 15:36:11 +08:00
    k9982874
        1
    k9982874  
       2017-08-10 18:07:42 +08:00 via iPhone   1
    jwt 本质也是 session
    baiyi
        2
    baiyi  
    OP
      2017-08-10 18:12:31 +08:00 via Android
    @k9982874

    本质指的是什么呢?
    会话状态吗?这个是不可避免的,无状态的本质也不是没有会话状态,而是会话状态不能保存在服务器端
    bazingaterry
        3
    bazingaterry  
       2017-08-10 18:14:11 +08:00 via iPhone   2
    session 可以在服务端注销,而一般的 JWT 不可以。
    baiyi
        4
    baiyi  
    OP
       2017-08-10 18:19:10 +08:00 via Android
    @bazingaterry

    这个我有想过,jwt 想要实现这个功能也是可以的,既然不能改变会话状态,可以改变会话中的资源状态,比如一般来说的用户,注销后可以修改资源状态,每次效验会话状态时,可以先查看资源状态

    比如一般情况下的用户会话状态,注销后可以在服务器端同步一条用户资源的注销情况,验证会话时查看是否已注销

    想的也没有太仔细,注销时间应该可以判断吧
    syncher
        5
    syncher  
       2017-08-10 18:21:28 +08:00 via Android   1
    JWT 怎么做延时?比如用户操作 30 分钟 token 失效这个功能 JWT 实现不了
    syncher
        6
    syncher  
       2017-08-10 18:22:52 +08:00 via Android   1
    #5 用户无操作 30 分钟 token 失效(手欠)
    baiyi
        7
    baiyi  
    OP
       2017-08-10 18:24:36 +08:00 via Android
    @syncher 会话状态的时效性吗,JWT 中也有对时间戳存储,也是具有时效性的
    baiyi
        8
    baiyi  
    OP
       2017-08-10 18:25:26 +08:00 via Android
    @syncher 可以用户每次请求后更新 jwt 的过期时间
    syncher
        9
    syncher  
       2017-08-10 18:28:51 +08:00 via Android   1
    @baiyi jwt 不是靠算法吗,怎么更新。除非产生新 token
    baiyi
        10
    baiyi  
    OP
       2017-08-10 18:30:55 +08:00 via Android
    @syncher 对,更新其中的时间戳,然后重新生成,并返回
    syncher
        11
    syncher  
       2017-08-10 18:31:42 +08:00 via Android   1
    @baiyi 每次请求返回新 token,前端不干了
    baiyi
        12
    baiyi  
    OP
       2017-08-10 18:33:29 +08:00 via Android
    @syncher 为什么呢?很麻烦吗,如果是存储在 cookie 中,甚至前端完全不需要处理的。app 一般不需要时效性,app 用的都是刷新机制
    syncher
        13
    syncher  
       2017-08-10 18:44:16 +08:00 via Android   1
    @baiyi 可能吧,我现在做的项目就是 JWT 认证。延时功能用 session 实现。
    U7Q5tLAex2FI0o0g
        14
    U7Q5tLAex2FI0o0g  
       2017-08-10 18:44:49 +08:00   1
    JWT 用在 API 中挺好的,但用在正常的客户操作上感觉会多出好多麻烦的事(我没用过),为啥不直接 seesion 解决呢
    baiyi
        15
    baiyi  
    OP
       2017-08-10 18:46:51 +08:00 via Android
    @syncher

    嗯,目前我的项目也是在用 jwt,对于这方面的需求只是我不成熟的理解,可能不能适应所有场景
    baiyi
       16
    baiyi  
    OP
       2017-08-10 18:50:18 +08:00 via Android
    @littleylv

    session 的缺点我在上面的问题内容中提到了,我认为 jwt 解决了这个问题,而 session 能实现的功能 jwt 也可以

    重要的是 session 不符合无状态风格……
    carlclone
        17
    carlclone  
       2017-08-10 18:53:14 +08:00 via Android   2
    session 和 cookie 不是为了解决 Http 无状态才产生的吗。。。怎么会符合无状态?
    baiyi
        18
    baiyi  
    OP
       2017-08-10 18:55:37 +08:00 via Android
    @carlclone 哎? cookie 也是解决无状态的吗?我认为将数据存在客户端是符合无状态的
    carlclone
        19
    carlclone  
       2017-08-10 19:01:21 +08:00 via Android   1
    @baiyi 哎我感觉你要补充一下 HTTP 的基础吧,session 就是 cookie 的升级版
    Mutoo
        20
    Mutoo  
       2017-08-10 19:04:22 +08:00   5
    cookie 的问题在于不能跨域,session 存在 cookie 里符合早期的 c/s 一对多的服务方式,而如果业务需求增长的话,servers 需要横向扩展,这要求 session 必须能在多台 server 之间同步共享。jwt 简化了这个共享的过程,只要任一 server 持有 private key 能解密 jwt 就能获得关键的用户数据,而不必把 session 在多台 server 间存放。
    baiyi
        21
    baiyi  
    OP
       2017-08-10 19:05:16 +08:00 via Android
    @carlclone 抱歉,那我可能对 cookie 和 session 的理解有错误。不过,如果说是为了解决无状态出的方案,那就是说明无状态是有缺陷的。能给点提点吗
    carlclone
        22
    carlclone  
       2017-08-10 19:06:53 +08:00 via Android   1
    客户端与服务器进行动态交互的 Web 应用程序出现之后,HTTP 无状态的特性严重阻碍了这些应用程序的实现,毕竟交互是需要承前启后的,简单的购物车程序也要知道用户到底在之前选择了什么商品。于是,两种用于保持 HTTP 连接状态的技术就应运而生了,一个是 Cookie,而另一个则是 Session。HTTP 本身是一个无状态的连接协议,为了支持客户端与服务器之间的交互,我们就需要通过不同的技术为交互存储状态,而这些不同的技术就是 Cookie 和 Session 了。
    baiyi
        23
    baiyi  
    OP
       2017-08-10 19:08:16 +08:00 via Android
    @Mutoo 对呀,所以 jwt 比 session 好,这是我的理解
    yuanfnadi
        24
    yuanfnadi  
       2017-08-10 19:10:07 +08:00   1
    @Mutoo 不需要 key 也可以获得关键数据,
    Mutoo
        25
    Mutoo  
       2017-08-10 19:11:20 +08:00   1
    @baiyi 这不代表 session 就会被取代呀。用 cookie 维护 session 是在 web 应用中非常直接的用法,没必要用大炮打蚊子。不过慢慢的越来越多的新框架会支持 jwt,而且在很多非 web 场景,也可以使用 jwt。
    WildCat
        26
    WildCat  
       2017-08-10 19:12:16 +08:00   1
    我现在用 django-rest-frameowork-jwt,感觉非常好 =。=
    但是如果传统后端渲染项目我还是会选择 session,就是为了简单。

    补充一句,貌似 Rails 的 session 默认 store 其实就是加密后的 cookies
    wellsc
        27
    wellsc  
       2017-08-10 19:12:49 +08:00   1
    我司在部分项目中已经用 jwt 取代 session 了。
    Mutoo
        28
    Mutoo  
       2017-08-10 19:13:20 +08:00   1
    @baiyi 无状态不是缺陷,相反是优势,这样才更有机会做均衡负载。但面对的问题就是如何在多 server 端维护同一 client 的状态,也就是 session。
    baiyi
        29
    baiyi  
    OP
       2017-08-10 19:14:37 +08:00 via Android
    @carlclone 原来是这段理解,这个我有看过,但并不认同,无状态不是不存在会话状态,而是不应该存储在服务器端。这是我对无状态的理解
    baiyi
        30
    baiyi  
    OP
       2017-08-10 19:18:16 +08:00 via Android
    @Mutoo
    @WildCat

    是不是说我想的是对的,jwt 比 session 好,只是因为历史遗留问题
    baiyi
        31
    baiyi  
    OP
       2017-08-10 19:19:29 +08:00 via Android
    @Mutoo jwt 就是解决了多个服务器同步会话状态的问题,因为它符合无状态
    baiyi
        32
    baiyi  
    OP
       2017-08-10 19:20:37 +08:00 via Android
    @所有人 感谢回复,手机浏览器不知道怎么感谢,回家后再点
    cxh116
        33
    cxh116  
       2017-08-10 19:20:45 +08:00   2
    http 协议有 session 吗? 没有.

    session 不过是基于 cookies 的服务端会话保存方案而已.

    jwt 的 token ,相当于 cookies 的 session id.两种方案无本质区别.


    比如 rails 的 session,就是把信息加密存到 cookies,每次请求都把 cookies 传过去,这样实现了你想要的无状态?
    carlclone
        34
    carlclone  
       2017-08-10 19:20:54 +08:00 via Android   1
    那你还是去看 RFC 吧 醉醉的
    Event
        35
    Event  
       2017-08-10 19:21:17 +08:00   1
    见 YII2 框架 有 Cookie 验证机制
    saberscarlet
        36
    saberscarlet  
       2017-08-10 19:22:10 +08:00 via Android   2
    我们这现在 web 项目用 redis 存 session,app 项目用 jwt
    andyangyu
        37
    andyangyu  
       2017-08-10 19:23:46 +08:00 via Android   1
    搭车问一个登录刷新活动状态的问题,我现在是每次请求通过 session 更新数据库,有其他更好的办法么?
    baiyi
        38
    baiyi  
    OP
       2017-08-10 19:24:42 +08:00 via Android
    @cxh116 对,会话状态存在客户端就是我认为的无状态,rails 的做法符合,但是我认为缺点是客户端无法获得会话状态,因为客户端是不能有加密的能力
    baiyi
        39
    baiyi  
    OP
       2017-08-10 19:25:13 +08:00 via Android
    @carlclone 好的,接受批评,谢谢指点
    baiyi
        40
    baiyi  
    OP
       2017-08-10 19:28:46 +08:00 via Android
    我见到的大部分框架都是通过加密存储,解密读取的方式利用 cookie,而 jwt 则是验证,客户端也可以查看会话状态,使用方向不同,我认为在鉴权方面 jwt 更好用
    gamexg
        41
    gamexg  
       2017-08-10 19:28:49 +08:00   1
    尺寸,session 保存一个 id 即可,jwt 要求所有 session 都存放在 cookie,保存太多的东西小心炸。
    baiyi
        42
    baiyi  
    OP
       2017-08-10 19:31:56 +08:00 via Android
    @gamexg 嗯,这是个问题,cookie 据我检索到的资料是 4kb 的存储大小,所以,我只放入了少量权限方面无法替代的内容,例如用户 id,权限 id
    baiyi
        43
    baiyi  
    OP
       2017-08-10 19:41:11 +08:00 via Android
    我觉得这里是问题的关键,我想再提出个问题,如果 jwt 不能包含所有内容,需要通过 id 等标示查找资源,那和 session 的区别呢……
    kiddult
        44
    kiddult  
       2017-08-10 19:41:25 +08:00   1
    刚查了一下,JWT 本身就是 session 吧,只是蛋疼的用 JSON 来表示
    baiyi
        45
    baiyi  
    OP
       2017-08-10 19:44:00 +08:00 via Android
    @kiddult 额,我认为是有区别的,jwt 本体含有所存储的会话状态
    tairan2006
        46
    tairan2006  
       2017-08-10 20:35:59 +08:00   1
    session 只是一个概念。。
    erobot
        47
    erobot  
       2017-08-10 20:40:48 +08:00   1
    不是做 web 的,查了一下说一下理解。

    http 协议设计是无状态的,业务如果要求会话的概念,那么需要用某种技术实现,通常都是基于 cookie 的。session_id 和 jwt 都是某种实现会话技术存储在客户端的数据而已,主要区别应该是在于格式和标准化程度,他们完全可以存储一样多的信息,如果空间没有限制的话。

    按照我的理解,正常 jwt 里面也应该是有类似 session_id 一样的信息的,不然就是密码本身而不是 token 了,尤其是类似登录状态,服务端应该有能力回收客户端的授权。

    关于客户端是否应该存储所有会话状态信息,rfc6265 里面有这样的说法:
    8.4. Session Identifiers
    Instead of storing session information directly in a cookie (where it might be exposed to or replayed by an attacker), servers commonly store a nonce (or "session identifier") in a cookie.
    ...
    Using session identifier cookies limits the damage an attacker can cause if the attacker learns the contents of a cookie because the nonce is useful only for interacting with the server (unlike non-nonce cookie content, which might itself be sensitive).
    bazingaterry
        48
    bazingaterry  
       2017-08-10 20:50:35 +08:00 via iPhone   1
    JWT 好像就是把 session 签名后存在了 Cookies 里面?
    loveCoding
        49
    loveCoding  
       2017-08-10 20:54:26 +08:00   2
    @littleylv #14 一般的项目 ,随着需求越来越复杂,比如登录设备限制 , 自动踢下线 . 不是 session 最后慢慢都会变成 session 样子的.
    yangff
        50
    yangff  
       2017-08-10 21:06:47 +08:00   1
    ……群魔乱舞
    Infernalzero
        51
    Infernalzero  
       2017-08-10 22:23:14 +08:00   1
    session 的应用要广得多,存服务端通过 session 属性可以做很多事
    huijiewei
        52
    huijiewei  
       2017-08-10 22:32:09 +08:00 via iPhone   1
    session 是有锁的
    sujin190
        53
    sujin190  
       2017-08-10 22:44:12 +08:00   1
    其实两者其实并没有什么区别
    session 现在如果存在服务器大多也会使用 redis 这样分布式存储方式,不存在不能横向扩展的问题,再者 session 也并不是一定要保存在服务器,完全可以加密放到 cookie 里
    jwt 也并不是没有问题,比如正常情况下要比 session_id 更大,需要消耗更多流量,挤占更多带宽,已经无法在服务端注销,那么久很难解决劫持问题
    此外 jwt 一般只会直接保存用户 id 这样信息,那么正常情况下还是需要用户更多信息,那么同样需要 redis 这样高效率缓存系统配合,那么效率上也并不能比 session 更高效
    sujin190
        54
    sujin190  
       2017-08-10 22:45:11 +08:00   1
    @huijiewei #52 真正使用其实并不需要,其实有点类似乐观锁之类的,就算短时不一致,问题也不大
    jy01264313
        55
    jy01264313  
       2017-08-10 23:53:07 +08:00   1
    session 不一定需要存在服务器端,cookie 里面存 session 一样可以非常简单
    msg7086
        56
    msg7086  
       2017-08-11 00:00:42 +08:00   2
    Session 是一个更宽泛的概念。
    JWT 原则上也是一种 Session。
    Rails 里用 Cookie based session 已经很久了,也是把 Session data 序列化加密以后存储 Cookie。
    主要缺点还是 Session data 比 Session ID 更耗费流量,每次请求(甚至当前域的静态文件也是)都要带上完整的 Session,非常耗费流量。另外 Cookie 本身还有长度限制问题。
    cnnblike
        57
    cnnblike  
       2017-08-11 02:38:23 +08:00   2
    我感觉 jwt 有一个不好实现,就是怎么保证服务器可以把用户踢下去呢?
    如果要能实现踢下线这个操作的化,你得在服务器端保存一个"latest effective timestamp"之类的,这又和一般的 session 又有什么区别呢?
    rason
        58
    rason  
       2017-08-11 07:51:52 +08:00 via iPhone   1
    感觉有人说的 session 非楼主所指的 session,具体与含义。
    rason
        59
    rason  
       2017-08-11 08:01:05 +08:00 via iPhone   1
    使用 jwt 就不需要用集中式 session 管理来解决分布式的问题,我只能说,jwt 是一种比 session 更优的会话方案。
    simaguo
        60
    simaguo  
       2017-08-11 08:57:59 +08:00   1
    最近用 jwt 正开发一个项目,体验中
    Clarencep
        61
    Clarencep  
       2017-08-11 09:14:31 +08:00   1
    个人感觉是 JWT 太长了
    mywaiting
        62
    mywaiting  
       2017-08-11 09:29:21 +08:00   3
    楼主目测只是看看文档,没有实际经手一个完整的项目

    session 只是一个概念,一个记录 client 状态的实现,这个角度来说,JWT 本身也是一种 session。而 HTTP 都是使用 cookie 来实现了,这点谁都一个卵样(极少数使用 URL 的 id 化来实现,然后无法避免一旦有人无意分享了这个 URL,顺便也把自己的登陆状态分享出去了,比如以前新浪微博的手机版,靠 URL 里面的 gsid 参数来别登陆的状态)。

    JWT 只是签名过的 cookie,一个有实现规范的协议而已,事实上就是一个加密的 cookie,保存信息容量有限,无法解决服务端过期的实现(可以服务端记录 JWT id 和 timestamp 做到,不过这样不是又回到服务器 session 的实现了么?)还有就是楼上的持久化劫持的问题,在需要大量保存用户数据(超过 JWT cookie 容量的时候),一样需要服务器侧的支持,此时又退化为服务器侧的 session 了。而 JWT 所说的只保存用户 id,根本就是伪命题,数据回到服务器,只有 id 你一样要根据 id 去数据库或者缓存查一次用户 user 自己的其他信息如 name,mail,这时候又退化为服务器侧的 session 了,完全失去其分布式的初衷

    服务器的 session 就是一个随机字符串 id 的 cookie 放客户端,服务器来保存该 id 对应的数据,的确是用分布式 session id 同步的问题。然而,多数时候,session id 的保存都在单独的 redis 服务器上了,不是淘宝那样的存在,几台 redis 足够你刷到数千万用户了,根本没有什么好担心的

    说到底,还是 HTTP 这个协议已经决定了你的实现的方法,session 能折腾的方向实在不多。而大多数网站的实现都是服务器端的 session,此时,你就应该好好想一下,JWT 是不是有天生的缺陷。

    再者退一万步来说,身份识别和保持这事情,不使用中心化的识别和认证是及其困难的事情,无论现在的各种签名、各种算法,其背后还是有着中心化的担保和识别的。

    道理都是简单如此

    以上,希望有用
    littleshy
        63
    littleshy  
       2017-08-11 10:04:03 +08:00   1
    jwt 适合分布式,但我真正需要分布式的网站也就那几家大厂。
    还不如用 session。
    baiyi
        64
    baiyi  
    OP
       2017-08-11 10:30:58 +08:00
    @mywaiting #62

    倒也不是没有项目经验, 只是之前想得太少

    session 存在的必要也了解, 只不过太过纠结于存储在服务器端还是客户端了.

    您的内容对我很有帮助, 感谢!
    kiddult
        65
    kiddult  
       2017-08-11 11:00:50 +08:00   1
    @baiyi JWT 存的用普通的也能搞定,不过感觉你说的是不是 J2EE 里面的 session ?实际用的时候,除非个人小站,不然不会把 session 放本地内存
    kiddult
        66
    kiddult  
       2017-08-11 11:05:36 +08:00   1
    @baiyi session 放服务器还是客户的都没事,各有利弊,服务器端放单独缓存里面,不要放本地内存就行了
    baiyi
        67
    baiyi  
    OP
       2017-08-11 11:10:46 +08:00
    @kiddult #66

    我认为 jwt 比 Session ID 好的一点在于对客户端来说是可见的, 服务器端只是校验

    当然, 不好的点也有, 太大了,增加了每次请求的负担
    superboss01
        68
    superboss01  
       2017-08-11 11:59:57 +08:00   2
    问这种问题就没搞清本质了(什么叫 SESSION,请参考该文字本身的意思)

    COOKIE 和 JWT 从本质上看都一样的,可进行用户的身份识别和认证,实现 SESSION 会话,不过侧重点不一样
    COOKIE 是传统的久产物,只有一个身份字符串
    JWT 虽然也是一个字符串,不过自身包含了身份字符串TOKEN,签名以及签名方式和一些额外的信息
    你可以自己实现一套自己的 JWT,比如 base64(jsonencode([{name:'enc',type:'md5'},{token:'xxx'},{sign:''}])),当然了 JWT 有自己的一套标准

    共同点:
    COOKIE 是浏览器自身进行了存储,在通信时候浏览器将 COOKIE 信息从存储地方取值后附加到了 HTTP 的 HEADER 头部进行了请求(也可以放入查询字符串)

    JWT 也是将信息放入 HTTP HEADER 头部(你放入查询字符串也可以)

    COOKIE JWT 都有过期时间,都有身份表示字符串

    微小不同点:
    COOKIE 依赖了浏览器和 COOKIE 自身的存储方式(比如域名相关)
    而 JWT 则脱离了这样约束,特别是当下浏览器和 APP 以及分布式的环境下则体现出了优势了
    ieiayaobb
        69
    ieiayaobb  
       2017-08-11 12:01:01 +08:00   1
    其实服务端注销这个需求是 JWT 的痛点,当然你可以把 JWT 当做一个 id_token 存在服务端,但这样做就舍弃了 token 的无状态的优势了
    superboss01
        70
    superboss01  
       2017-08-11 12:07:42 +08:00   1
    @ieiayaobb 前 2 天都帮人做过 JWT 的实现 业务 JWT 是不需要存储在服务器端的

    问题就是过期问题 如果用户在登录获取到 JWT 这个字符串后 我没有采用 JWT 自身的过期,因为需要给用户再从新发送新的有效期 JWT 很明显有些麻烦了

    而是采用了 REDIS 进行下 JWT 缓存 用户在进行下 API 请求的时候,我就将该 JWT 在 REDIS 里面进行时间的延长
    sampeng
        71
    sampeng  
       2017-08-11 12:09:01 +08:00   1
    每次有人要用 jwt。我就想怼回去。。。
    个人感觉 jwt 更多的是在移动应用里面使用。为啥要这么用?
    因为我见过的移动端开发都说不能支持 cookie。也就不能支持 session。既然要 url 传 sessionid。那就干脆 jwt 了。。
    这个逻辑我也表示很无语。。。
    baiyi
        72
    baiyi  
    OP
       2017-08-11 12:36:19 +08:00
    @superboss01 #68

    我对比的不是 jwt 和 cookie , 而是 session id 和 jwt
    baiyi
        73
    baiyi  
    OP
       2017-08-11 12:37:35 +08:00
    @ieiayaobb #69

    服务器注销可以不需要存储所有的 jwt 内容, 只存储需要注销的 jwt , 根据注销时间判断, 这是我的看法,
    orFish
        74
    orFish  
       2017-08-11 12:48:43 +08:00   1
    jwt 本质也是 token,只是可以解析后获得部分用户信息等。

    jwt 经常也都是要存 redis 等缓存的
    jarlyyn
        75
    jarlyyn  
       2017-08-11 12:51:23 +08:00   1
    楼主的问题无非是吧 session 数据放在服务器端还是客户端而已。

    本质上还是一个东西。
    baiyi
        76
    baiyi  
    OP
       2017-08-11 12:58:59 +08:00
    @orFish #74

    如果说 jwt 能保存所有的关于身份认证的会话状态, 又不会超出太多大小, 是不是就不需要服务器端缓存了
    baiyi
        77
    baiyi  
    OP
       2017-08-11 13:00:22 +08:00
    @jarlyyn #75

    如果说到本质, 那都是 会话状态
    baiyi
        79
    baiyi  
    OP
       2017-08-11 14:56:31 +08:00
    @newkedison #78

    作者写的很有水平

    jwt 一旦有状态, 那无非是个更为麻烦的 Session ID

    而无状态的 jwt 又有好多缺陷, 很苦恼

    作者本人似乎也在 V2EX
    newkedison
        80
    newkedison  
       2017-08-11 15:06:51 +08:00   1
    @baiyi #79

    我也觉得写的不错,jwt 可能用在 app 上还是有用武之地的吧,在 web 上还是老实用 session 就行了。
    baiyi
        81
    baiyi  
    OP
       2017-08-11 15:11:16 +08:00
    @newkedison #80

    嗯, 作者的一个 [用无状态 JWT 实现一个精确统计在线用户数量的功能,再来重新说这个话] 直戳我的心上, 想了好久没想到解决办法......
    orFish
        82
    orFish  
       2017-08-11 15:14:45 +08:00   1
    @baiyi 是不需要,但是,如果有 jwt token revoke 的需求,还是要存 cache 啊,而且 jwt 用的话,key 一旦泄露就 GG

    我们之前项目中用 jwt,但是还是需要去 redis 做校验。
    baiyi
        83
    baiyi  
    OP
       2017-08-11 15:28:41 +08:00
    @orFish #82

    jwt 需要注销, 我的设想是: 服务器端既然不能控制会话状态, 那么, 可以控制用户资源状态, 给其添加一个注销时间, 时常 = jwt 的最大有效期, 每次 jwt 校验过后, 还要校验是否有符合注销时间

    至于 key 被偷不再考虑的范围内
    baiyi
        84
    baiyi  
    OP
       2017-08-11 15:29:46 +08:00
    @baiyi #83

    不过, 虽然没有在服务器端保存 jwt 的内容, 但算不算给 jwt 添加状态了呢
    orFish
        85
    orFish  
       2017-08-11 22:07:47 +08:00
    @baiyi revoke 是要马上失效,而不是让 token 在原来的有效期后再失效。
    baiyi
        86
    baiyi  
    OP
       2017-08-12 08:18:26 +08:00
    @orFish

    我是这么理解的, 服务器增加一个注销时间戳, 所有生成 token 的时间小于注销时间戳的全部拒绝权限
    orFish
        87
    orFish  
       2017-08-12 22:05:49 +08:00
    @baiyi 显然你还是没理解我意思。。。假如,你现在给用户 A 发放了个 token TokenA, jwt 可以从此 token 得到过期时间是 2017-09.01 ,但是用户在 2017-08-20 修改了密码,需要把 TokenA revoke 掉使其失效,你不存 cache 你能实现么。(不考虑 token 黑名单)
    baiyi
        88
    baiyi  
    OP
       2017-08-12 23:51:23 +08:00
    @orFish #87 你知道你的 jwt 发布的过期时间是多少, 比如说 7 天, 那么过期时间 -7 天, 得出生成的时间戳, 或者 jwt 里也有存储发布时间的。 注销时间是 7 天内的, 那么很容易得出这个 jwt 过期了
    orFish
        89
    orFish  
       2017-08-13 12:16:53 +08:00
    @baiyi 是我,我知道我发布的过期时间是 2017-09.01 ,但是 revoke 就是要提前过期。
    baiyi
        90
    baiyi  
    OP
       2017-08-13 12:53:32 +08:00
    @orFish #89

    恩, 我是这么想的, 过期时间是 2017-09-01, 那么已知你的过期时间和总有效期, 因为毕竟是你签发的吗,你一定知道总有效期的。

    假设总有效期是 7 天 , 那么签发日期就是 2017-08-24,8 月份有 31 号, 我没算错吧。

    用户在 2017-08-27 提出注销请求, 服务器记录 2017-08-27 的注销时间, 有效期为 jwt 的总有效期。

    这时 2017-08-24 签发的请求过来后, 就能判断出他的请求失败了
    orFish
        91
    orFish  
       2017-08-14 19:59:53 +08:00
    @baiyi 服务器记录 2017-08-27 的注销时间 都记录了,还不如存 token 了吧。
    lml12377
        92
    lml12377  
       2017-08-31 10:31:26 +08:00
    @Mutoo 多负载机的会话解决方案,即使牵扯到 REST,不也应该是集中存储 session 吗(比如 redis 集群,或者存到库中)?
    lml12377
        93
    lml12377  
       2017-08-31 10:43:11 +08:00
    @Mutoo 我可能理解错了~正常是不是客户端使用账号密码请求 api,校验成功生成 token,不管是哪一台负载机 token 统一存到一处比如 redis,比如网页端则可以将 token 关联到 cookie 来维持 web 端的登陆?刷新页面,网页后端从 session 中拿到 token 请求 api ?
    gmywq0392
        94
    gmywq0392  
       2017-09-01 09:51:50 +08:00
    hack news 上有很多讨论,看上去主要是对一个既有的 token 没有一个理想的失效机制,但在 token 里面放个 expire 的方式感觉就能解决了哇。v2er 有兴趣可以看下他们的讨论,看看我们还有什么未论及的弊端。
    1. https://news.ycombinator.com/item?id=13865459
    2. https://news.ycombinator.com/item?id=11895440
    3. https://news.ycombinator.com/item?id=14290114

    还有一个问题就是 jwt 头的算法标识,如果 token 里的加密算法是由客户端决定的,那么服务器的每次校验签名,都是根据那个算法来的,这个会让服务器显得很肉鸡。这个个人觉得相当尴尬,不是我们开发人员能允许的存在。

    另外啊,使用上来讲,jwt 和传统的 session cookie 就像传值和传引用一样,如果想够纯粹那就不能每次都 hit db or redis etc,这时 token 里的内容就会敏感起来,会担心它的泄密与可靠,在这个点上,假设 token 是不对外暴露的( https ),难以模仿的或者说模仿成本过高的(哈哈一个可行性猜测),那么适用性就广泛些。做不到以上的话,还是建议只用作微服务间内部的通信凭证,与 C 端的通信,由服务网关那维护 session 的机制。哈哈这里又 stateful 了。
    gmywq0392
        95
    gmywq0392  
       2017-09-01 09:57:08 +08:00
    @gmywq0392 干,应该是 hacker news。第二段有个错误,“如果 token 里的加密算法是由客户端决定的” 应该为 “如果 token 里的加密算法是可以由客户端决定的”
    baiyi
        96
    baiyi  
    OP
       2017-09-01 10:00:48 +08:00
    @gmywq0392 #94 jwt 的算法不是客户端决定的, 是另外一台服务器决定的, 因为 JWT 并不是客户端生成的, 他方便的是多台服务器间的沟通.

    token 主要的失效问题是只能被动失效, 就是过期时间, JWT 中有这个规范. 现在想要的效果是主动失效, 按照我上面回答中的处理方法, 服务器还是要存储 context. 虽然比存储 session 要少得多, 但还是有些不太好.
    gmywq0392
        97
    gmywq0392  
       2017-09-01 10:10:14 +08:00
    @baiyi 看下 95,我上面说错了,骚瑞 all。
    Zzdex
        98
    Zzdex  
       2018-06-08 10:16:12 +08:00 via iPhone
    项目没用 JWT 原因之一就是无法服务端注销 只能前端假注销
    JWT 想实现 那就必须在服务端留 key 那不就和 session 一样了吗
    JasonLaw
        99
    JasonLaw  
       2021-03-07 15:36:11 +08:00 via iPhone
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1003 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 35ms UTC 18:42 PVG 02:42 LAX 11:42 JFK 14:42
    Do have faih in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86