关于前后端分离中的 Session 和 Token ,请教大家几个问题。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
mitu9527
V2EX    程序员

关于前后端分离中的 Session 和 Token ,请教大家几个问题。

  •  
  •   mitu9527 2020-09-01 22:09:39 +08:00 5276 次点击
    这是一个创建于 1954 天前的主题,其中的信息可能已经有所发展或是发生改变。

    1.对于会话来说,JWT 真的算 Token 么?虽然名字中带 Token,但是对于会话来说,我觉得 JWT 其实更像是一种“客户端会话”。客户端会话虽然有一些吸引力,但是带来的问题好像比服务端会话更多,怎么还有好多人推荐使用,是我学艺不精,还是他们没搞清楚?

    2.服务端会话已经很成熟易用了,在前端也只需要保存一个会话 ID 而已,在传统的开发模式中这个会话 ID 基本上都是保存在 Cookie 中的。如果在前后端分离这种开发模式下,真的用不了 Cookie (比如说部分客户端不支持 Cookie 或者跨域了),那直接基于 HTTP 头部实现一种替代的会话 ID 传输方式,然后再找一个地方存储这个会话 ID,不就可以了么?我看好像也有些人这么做并且管这个叫 Token 。

    3.我还见到一些人说“先输入用户名和密码进行登陆,成功后返回一个 Token,然后后续请求都带上这个 Token,定期更换即可”。从功能上讲,这种 Token 感觉十分类似我们做“保持登陆 7 天”时的那种自动登陆 Token,是么?那这种 Token 和会话好像已经没关系了啊!

    所以说在前后端分离中不使用 Cookie 的情况下,Session 和 Token 到底该怎么用?

    第 1 条附言    2020-09-02 10:55:30 +08:00
    关于前后端分离中常说的 Token 和 Session,我已经研究了一天了,看了得有几十篇文章了。说说我目前的看法吧。

    Token 本质上其实就是“客户端会话”,而 Session 则是经典的“服务端会话”。JWT 就是一种设计良好的、得到广泛支持的 Token (如果我决定用 Token 而不是用 Session,那我大概率也会直接用 JWT,不会自己去设计一套 Token )。

    虽然很多文章中列出了 Token 的优点,比如安全性啊、跨域啊、所有客户端都可以支持,等等一大堆,其实好多都是和 Cookie 相关的,不应该拿出来说事儿,剩下的也不怎么经得起仔细琢磨。最后,我认为 Token 最大的优点就是其“客户端会话”本质中的“客户端”三个字,也就是好多人说的“去中心化”和“无状态”。而 Token 最大的缺点是:服务端主动销毁一个 Token 时,如果不在服务端记录,比如通过 Redis,那么保存在客户端的 Token 仍然会保持有效。虽然为 Token 所使用的 Redis 在量级上不如为 Session 所使用的 Redis 大,但这样做多少还是有些违背了“去中心化”的初衷。这个缺点从本质上来讲,还是因为其“客户端”引起的。所以说 Token 成也客户端,败也客户端。

    所以说 Token 和 Session 的比较实际上是“客户端会话”和“服务端会话”的比较。我看好多人在字里行间都透露着 Token 比 Session 更“优秀”,是替代 Session 的;但是在我看来 Token 只不过比 Session 更“新”罢了,它和 Session 不是纯粹的替代关系,应该根据实际情况决定使用哪一个,甚至说结合二者。

    这就是我目前对 Token 和 Session 的认知,欢迎大家指正。
    28 条回复    2020-09-02 12:39:05 +08:00
    Ptu2sha
        1
    Ptu2sha  
       2020-09-01 22:23:05 +08:00   1
    多个业务的情况下 Session 是单个业务维护登陆用户信息的
    而 token 是多个系统共用的登陆鉴权的
    KuroNekoFan
        2
    KuroNekoFan  
       2020-09-01 22:41:23 +08:00 via iPhone   2
    jwt 是去中心化,自包含的,必须理解这两点
    Mithril
        3
    Mithril  
       2020-09-01 22:47:57 +08:00   1
    这个东西主要是分布式或者负载均衡里面用,当你同一个用户的两个请求打到不同服务实例上的时候,这两个实例都需要有能力验证它的合法性。
    session 的话你就得保证两个请求都进到同一个服务器里才行。或者你确定你的业务规模用不着做这些东西,那直接用 session 最方便。
    wellsc
        4
    wellsc  
       2020-09-01 22:49:30 +08:00 via iPhone
    @Mithril 分布式 session 了解一下
    mitu9527
        5
    < href="/member/mitu9527" class="dark">mitu9527  
    OP
       2020-09-01 22:51:38 +08:00
    @KuroNekoFan 但是我感觉 JWT 的缺点也挺多的,觉得至少在会话这块用起来不合适。
    mitu9527
        6
    mitu9527  
    OP
       2020-09-01 22:53:48 +08:00
    @Mithril 服务端会话有很多种成熟的方案了,小型、中型和大型架构都有,这个觉得不是问题。
    tinycold
        7
    tinycold  
       2020-09-01 22:55:18 +08:00 via Android   1
    其实你说的那些都不是啥问题,JWT 最大的问题是一旦发出去了,在它的失效时间到来之前你永远无法撤销它的认证,要是存 redis 里过滤那就太好笑了。

    它最大的好处就是"无状态",正如楼上说的,如果要考虑到复杂的认证 /鉴权系统,JWT 是很有优势的,因为 JWT 的灵活性远远高于 session 。如果只是简单的客户端认证,其实和前后端是否分离关系不大,就直接用自带的 session 认证系统基本就能 hold 住。否则你还得设计 token 分发,刷新,过期处理等等麻烦的事情。

    不过,小孩子才做选择,成年人什么都要。你可以用 jwt 来存你的 session id,这样不就完美解决这个问题了!!!(狗头,狗头)
    KuroNekoFan
        8
    KuroNekoFan  
       2020-09-01 22:57:01 +08:00 via iPhone
    @mitu9527 时代变了,以前可能凭证( credentials )和 会话( session )混在了一起,但现在,可能不这样做了(当然你还是可以这样做),而 jwt 的好处在于,payload 是自定义格式的数据
    mitu9527
        9
    mitu9527  
    OP
       2020-09-01 23:01:42 +08:00
    @tinycold 嗯,JWT 最大的特点是存在客户端,而不是服务器端,所以“无状态”,但也正式因为没有存在服务端,所以服务端没办法主动让其失效,只能等其过期。
    timothyqiu
        10
    timothyqiu  
       2020-09-01 23:02:43 +08:00   2
    Token 这个词本身不应该狭隘地理解为某个特定领域 /框架中的含义,计算机科学范畴广泛使用 Token 这个术语,本质上只要是「一段对用户含义不透明的数据」都可以叫 Token 。JWT 既然是 JSON Web Token,那它就是 Token 。

    「服务端会话还是客户端会话」与「使用 Cookie 还是 Token 」是正交的,Cookie 和 Token 只是信息的载体,信息是 SessionID 还是完整的 Session 数据其实无所谓。JWT 的优势是有签名,可以防止数据被篡改。

    前后端分离一般见到的都是用 Authorization 报头传 JWT 。RESTful API 的话客户端会话比较多,因为好实现、方便 HTTP 缓存、方便 Scale 。
    mitu9527
        11
    mitu9527  
    OP
       2020-09-01 23:14:14 +08:00
    @timothyqiu 有点懵了,不过还是要说声感谢!
    j2gg0s
        12
    j2gg0s  
       2020-09-01 23:20:20 +08:00   1
    在你的描述中,session 是指 cookie 中的 kv,token 是指要 header 里面的 kv,那么 session 的相对优势是不需要请求时手动处理,劣势在于 cookie 使用时不易 cross-domain 和 samesite 之类的限制。

    JWT 的优势在于可以存储一些无害的信息,减少调用,同时可以通过校验来避免恶意的 DDOS 击穿系统。绝大部分的操作我理解还是不会直接相信 JWT 中的数据。
    xuanbg
        13
    xuanbg  
       2020-09-02 07:26:20 +08:00   1
    @tinycold 复杂的认证 /鉴权系统 JWT 根本做不了。把复杂的授权信息放 payload 就是个笑话,而且,最要命的是做不到授权信息的动态更新。


    @mitu9527 JWT 最大的特点也是它的最大缺点。
    Mithril
        14
    Mithril  
       2020-09-02 07:39:08 +08:00
    @wellsc 去中心化了解一下
    Mithril
        15
    Mithril  
       2020-09-02 07:52:00 +08:00
    @mitu9527 这个就是问题,你可以了解一下这些成熟的服务端会话和 JWT 有什么区别。
    本质上 JWT 只是解决了“Server 必须要存储 session 信息”这么个事。
    因为 Server 端需要存储 session 信息,所以分布式或者复杂均衡情况下需要通过 session 共享,或者数据库,nginx 配置等等方法要么在多个实例里共享 session,要么保证同一个用户的每次请求都打到一个实例里。
    而 JWT 你可以根据需求做到不需要先验知识的验证,从而保证多个实例在验证的时候不需要共享先验知识。Token 这种东西也足够灵活,如果简单的验证不够的话你也可以往里面存个 session id 。
    Mutoo
        16
    Mutoo  
       2020-09-02 08:04:30 +08:00
    JWT 有很多额外的好处。例如可以用非对称加密鉴权,这种无状态鉴权除了 scaling 的好外以外,还有其它玩法:只要把 public key (注意不是 private key )交给乙方,乙方就可以快速鉴权甲方用户,并且也是无状态的,无无需额外的请求。
    renmu123
        17
    renmu123  
       2020-09-02 08:32:17 +08:00 via Android
    session 是个概念,而 token 是一个具体实现,cookie 也是
    meshell
        18
    meshell  
       2020-09-02 09:10:11 +08:00   1
    token 无法主动删除更新用户的凭证.
    dany813
        19
    dany813  
       2020-09-02 09:23:19 +08:00
    老哥们一般是怎么刷新 token 的,定时刷新吗
    wellsc
        20
    wellsc  
       2020-09-02 10:01:46 +08:00
    @Mithril jwt token 无法被服务端主动撤销,以及潜在的安全问题,就注定无法替代 session ,个人感觉 jwt 存储 session id,服务端使用分布式 session 才是比较好的解决方案
    mitu9527
        21
    mitu9527  
    OP
       2020-09-02 10:57:44 +08:00
    @dany813 一般都会设置一个过期时间,这个过期时间也保存在客户端,并随每次请求发送给服务端,服务端做验证,判断其是否过期,过期后就告知客户端该 Token 无效,让客户端重新发起登陆请求去重新生成新的 Token 就可以了。
    also24
        22
    also24  
       2020-09-02 10:59:09 +08:00   1
    悄悄的丢链接:
    t/656457

    JWT 是一种 token 生成方式。
    Session 是代指一整个会话过程的虚拟概念。

    二者并不在同一个层级。
    mitu9527
        23
    mitu9527  
    OP
       2020-09-02 11:04:14 +08:00
    @also24 这篇文章我看到了。
    siganushka
        24
    siganushka  
       2020-09-02 11:46:05 +08:00   1
    “会话”只是一个抽象概念,不管是传统的服务端 session,还是 API 里的 JWT,本质都是把两次本不相干的链接关联起来,session 里的 session_id 和 jwt 中的 token 都需要服务端管理和维护,由客户端负责存储,两次链接发送的值一样,即可认为是同一个会话。

    像 JWT 一样,服务端的 session 也可以自定义 session_id 和存储逻辑,因此本质上我认为他们是同一个抽象对于不同场景的不同实现,其直接有细微差别,比方说如果你把 session_id 在 cookie 中的 key 改成 token,值为 JWT 的 token 值行不行?然后自己实现存储逻辑,这不和传统的服务端 session 一样么?

    之所以你觉得不一样,可能是因为他们的场景有细微的差别,1 是浏览器对于 cookie 的支持相对于 APP (或各种客户端)更好,因此默认不需要客户端手动操作,服务端就能实现整个 session 实现。2 是对于 JWT 的定义中,一旦服务端颁发 token 给客户端,在过期之前服务端无法撤销。

    如果让你自己实现一个类似服务端的 session 功能,你想想你该怎么做?想到最后可能就是另一个 JWT !
    timothyqiu
        25
    timothyqiu  
       2020-09-02 11:52:03 +08:00
    按照附言里的定义,大概比较一下:

    1. 客户端可以直接修改 Session 里的会话 ID 来冒充其它人;但客户端没法修改 JWT 里的数据,因为它是签了名的。

    2. 客户端可以直接修改 Session 的 Cookie 过期时间(甚至不理会),所以服务器必须自行维护会话过期时间;但客户端没法修改 JWT 里的过期时间,因为它是签了名的,所以服务器不用维护会话过期时间。

    3. 服务器可以很方便地主动结束 Session,无需额外设施; Token 如果需要服务器主动回收,则必须自行维护黑名单。

    不过对于 Token 在第 3 点 Token 所引入的额外设施,Session 是在第 2 点里引入的,而且 Token 只需追踪服务器主动结束的黑名单,Session 必须则必须为所有已登录用户存一份。

    但话还是得说回来,不要重新定义概念,按照正常的定义会更好地理解你想研究的问题。Session 就是会话,你称作 Session 的东西是「基于 Cookie 的服务器会话」,你称作 Token 的东西是「基于 Token 的客户端会话」。Cookie 也可以客户端会话,Token 也可以服务器会话。Cookie 和 Token 是一类东西,Session 是另一类东西。
    timothyqiu
        26
    timothyqiu  
       2020-09-02 12:00:20 +08:00
    啊,第一点里如果你的框架签名或者加密了会话 ID,就和 JWT 没啥区别了 ♂
    mitu9527
        27
    mitu9527  
    OP
       2020-09-02 12:09:54 +08:00
    @timothyqiu
    1.我拿到了 JWT,还改它干啥,直接盗用了;这和会话 ID 被盗取是一样的。再者会话 ID 就算被改了,服务端也不会认。只要会话 ID 生成的方法没问题,想碰撞会话 ID 也是非常难的。
    2.那个是 Cookie 的问题吧。再说在服务端会话数据里面加一个过期时间,和在 JWT 中加一个过期时间有什么本质区别么?能在 JWT 中加,那也能在服务端会话中加。
    3. 这个是一个本质的区别。

    在前后端分离这块,很多人所说的 Token 确实就是客户端会话,那些 Token 的优缺点也都是客户端会话的优缺点。不过在超出这个范畴,那 Token 的含义就不局限于“会话”了。
    timothyqiu
        28
    timothyqiu  
       2020-09-02 12:39:05 +08:00
    @mitu9527 对,所以本质上是想要比较客户端会话和服务器会话。

    Token 和 Cookie 都只是数据的载体,优缺点没什么大区别。无论是加密 /签名 Cookie 数据,还是往 Cookie 里额外存过期时间,本质上就像楼上那个哥们说的,完善到最后你会发现往 Cookie 里存的就是另一种形式的 JWT 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5799 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 30ms UTC 02:26 PVG 10:26 LAX 18:26 JFK 21:26
    Do have faith in what you're doing.
    ubao msn 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