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
Ptu2sha 2020-09-01 22:23:05 +08:00 1
多个业务的情况下 Session 是单个业务维护登陆用户信息的
而 token 是多个系统共用的登陆鉴权的 |
2
KuroNekoFan 2020-09-01 22:41:23 +08:00 via iPhone 2
jwt 是去中心化,自包含的,必须理解这两点
|
3
Mithril 2020-09-01 22:47:57 +08:00 1
这个东西主要是分布式或者负载均衡里面用,当你同一个用户的两个请求打到不同服务实例上的时候,这两个实例都需要有能力验证它的合法性。
session 的话你就得保证两个请求都进到同一个服务器里才行。或者你确定你的业务规模用不着做这些东西,那直接用 session 最方便。 |
5
mitu9527 OP @KuroNekoFan 但是我感觉 JWT 的缺点也挺多的,觉得至少在会话这块用起来不合适。
|
7
tinycold 2020-09-01 22:55:18 +08:00 via Android 1
其实你说的那些都不是啥问题,JWT 最大的问题是一旦发出去了,在它的失效时间到来之前你永远无法撤销它的认证,要是存 redis 里过滤那就太好笑了。
它最大的好处就是"无状态",正如楼上说的,如果要考虑到复杂的认证 /鉴权系统,JWT 是很有优势的,因为 JWT 的灵活性远远高于 session 。如果只是简单的客户端认证,其实和前后端是否分离关系不大,就直接用自带的 session 认证系统基本就能 hold 住。否则你还得设计 token 分发,刷新,过期处理等等麻烦的事情。 不过,小孩子才做选择,成年人什么都要。你可以用 jwt 来存你的 session id,这样不就完美解决这个问题了!!!(狗头,狗头) |
8
KuroNekoFan 2020-09-01 22:57:01 +08:00 via iPhone
@mitu9527 时代变了,以前可能凭证( credentials )和 会话( session )混在了一起,但现在,可能不这样做了(当然你还是可以这样做),而 jwt 的好处在于,payload 是自定义格式的数据
|
9
mitu9527 OP @tinycold 嗯,JWT 最大的特点是存在客户端,而不是服务器端,所以“无状态”,但也正式因为没有存在服务端,所以服务端没办法主动让其失效,只能等其过期。
|
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 。 |
11
mitu9527 OP @timothyqiu 有点懵了,不过还是要说声感谢!
|
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 中的数据。 |
13
xuanbg 2020-09-02 07:26:20 +08:00 1
|
15
Mithril 2020-09-02 07:52:00 +08:00
@mitu9527 这个就是问题,你可以了解一下这些成熟的服务端会话和 JWT 有什么区别。
本质上 JWT 只是解决了“Server 必须要存储 session 信息”这么个事。 因为 Server 端需要存储 session 信息,所以分布式或者复杂均衡情况下需要通过 session 共享,或者数据库,nginx 配置等等方法要么在多个实例里共享 session,要么保证同一个用户的每次请求都打到一个实例里。 而 JWT 你可以根据需求做到不需要先验知识的验证,从而保证多个实例在验证的时候不需要共享先验知识。Token 这种东西也足够灵活,如果简单的验证不够的话你也可以往里面存个 session id 。 |
16
Mutoo 2020-09-02 08:04:30 +08:00
JWT 有很多额外的好处。例如可以用非对称加密鉴权,这种无状态鉴权除了 scaling 的好外以外,还有其它玩法:只要把 public key (注意不是 private key )交给乙方,乙方就可以快速鉴权甲方用户,并且也是无状态的,无无需额外的请求。
|
17
renmu123 2020-09-02 08:32:17 +08:00 via Android
session 是个概念,而 token 是一个具体实现,cookie 也是
|
18
meshell 2020-09-02 09:10:11 +08:00 1
token 无法主动删除更新用户的凭证.
|
19
dany813 2020-09-02 09:23:19 +08:00
老哥们一般是怎么刷新 token 的,定时刷新吗
|
20
wellsc 2020-09-02 10:01:46 +08:00
@Mithril jwt token 无法被服务端主动撤销,以及潜在的安全问题,就注定无法替代 session ,个人感觉 jwt 存储 session id,服务端使用分布式 session 才是比较好的解决方案
|
21
mitu9527 OP @dany813 一般都会设置一个过期时间,这个过期时间也保存在客户端,并随每次请求发送给服务端,服务端做验证,判断其是否过期,过期后就告知客户端该 Token 无效,让客户端重新发起登陆请求去重新生成新的 Token 就可以了。
|
22
also24 2020-09-02 10:59:09 +08:00 1
|
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 ! |
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 是另一类东西。 |
26
timothyqiu 2020-09-02 12:00:20 +08:00
啊,第一点里如果你的框架签名或者加密了会话 ID,就和 JWT 没啥区别了 🤷♂️
|
27
mitu9527 OP @timothyqiu
1.我拿到了 JWT,还改它干啥,直接盗用了;这和会话 ID 被盗取是一样的。再者会话 ID 就算被改了,服务端也不会认。只要会话 ID 生成的方法没问题,想碰撞会话 ID 也是非常难的。 2.那个是 Cookie 的问题吧。再说在服务端会话数据里面加一个过期时间,和在 JWT 中加一个过期时间有什么本质区别么?能在 JWT 中加,那也能在服务端会话中加。 3. 这个是一个本质的区别。 在前后端分离这块,很多人所说的 Token 确实就是客户端会话,那些 Token 的优缺点也都是客户端会话的优缺点。不过在超出这个范畴,那 Token 的含义就不局限于“会话”了。 |
28
timothyqiu 2020-09-02 12:39:05 +08:00
@mitu9527 对,所以本质上是想要比较客户端会话和服务器会话。
Token 和 Cookie 都只是数据的载体,优缺点没什么大区别。无论是加密 /签名 Cookie 数据,还是往 Cookie 里额外存过期时间,本质上就像楼上那个哥们说的,完善到最后你会发现往 Cookie 里存的就是另一种形式的 JWT 。 |