首页   注册   登录
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 · 12965 次点击
    这是一个创建于 900 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近在细读 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 信息, 同样违反 [无状态] 约束
    98 回复  |  直到 2018-06-08 10:16:12 +08:00
    k9982874
        1
    k9982874   2017-08-10 18:07:42 +08:00 via iPhone   ♥ 1
    jwt 本质也是 session
    baiyi
        2
    baiyi   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   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   2017-08-10 18:24:36 +08:00 via Android
    @syncher 会话状态的时效性吗,JWT 中也有对时间戳存储,也是具有时效性的
    baiyi
        8
    baiyi   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   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   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 实现。
    littleylv
        14
    littleylv   2017-08-10 18:44:49 +08:00   ♥ 1
    JWT 用在 API 中挺好的,但用在正常的客户操作上感觉会多出好多麻烦的事(我没用过),为啥不直接 seesion 解决呢
    baiyi
        15
    baiyi   2017-08-10 18:46:51 +08:00 via Android
    @syncher

    嗯,目前我的项目也是在用 jwt,对于这方面的需求只是我不成熟的理解,可能不能适应所有场景
    baiyi
        16
    baiyi   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   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   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   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   2017-08-10 19:14:37 +08:00 via Android
    @carlclone 原来是这段理解,这个我有看过,但并不认同,无状态不是不存在会话状态,而是不应该存储在服务器端。这是我对无状态的理解
    baiyi
        30
    baiyi   2017-08-10 19:18:16 +08:00 via Android
    @Mutoo
    @WildCat

    是不是说我想的是对的,jwt 比 session 好,只是因为历史遗留问题
    baiyi
        31
    baiyi   2017-08-10 19:19:29 +08:00 via Android
    @Mutoo jwt 就是解决了多个服务器同步会话状态的问题,因为它符合无状态
    baiyi
        32
    baiyi   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   ♥ 1
    我们这现在 web 项目用 redis 存 session,app 项目用 jwt
    andyangyu
        37
    andyangyu   2017-08-10 19:23:46 +08:00 via Android   ♥ 1
    搭车问一个登录刷新活动状态的问题,我现在是每次请求通过 session 更新数据库,有其他更好的办法么?
    baiyi
        38
    baiyi   2017-08-10 19:24:42 +08:00 via Android
    @cxh116 对,会话状态存在客户端就是我认为的无状态,rails 的做法符合,但是我认为缺点是客户端无法获得会话状态,因为客户端是不能有加密的能力
    baiyi
        39
    baiyi   2017-08-10 19:25:13 +08:00 via Android
    @carlclone 好的,接受批评,谢谢指点
    baiyi
        40
    baiyi   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   2017-08-10 19:31:56 +08:00 via Android
    @gamexg 嗯,这是个问题,cookie 据我检索到的资料是 4kb 的存储大小,所以,我只放入了少量权限方面无法替代的内容,例如用户 id,权限 id
    baiyi
        43
    baiyi   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   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   ♥ 1
    我感觉 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   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   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   2017-08-11 12:36:19 +08:00
    @superboss01 #68

    我对比的不是 jwt 和 cookie , 而是 session id 和 jwt
    baiyi
        73
    baiyi   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   2017-08-11 12:58:59 +08:00
    @orFish #74

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

    如果说到本质, 那都是 会话状态
    baiyi
        79
    baiyi   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   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   2017-08-11 15:28:41 +08:00
    @orFish #82

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

    至于 key 被偷不再考虑的范围内
    baiyi
        84
    baiyi   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   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   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   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   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 一样了吗
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   771 人在线   最高记录 5168   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 32ms · UTC 21:16 · PVG 05:16 · LAX 13:16 · JFK 16:16
    ♥ Do have faith in what you're doing.