JWT 服务端怎么理解不需要存储 session

2019-02-18 19:27:43 +08:00
 Lateautumn

接触了一下 jwt,很多说法说服务端是无状态的,我这里有个疑问,当客户端是发送 token 过来 ,服务端怎么验证这个 token 的真实性,以及是哪个用户,如果把用户信息放在 payload 里面的话可以,那怎么去验证这个呢,不是还得去数据库查吗,如果不验证怎么知道是哪个用户?

8816 次点击
所在节点    Python
66 条回复
rayingecho
2019-02-18 20:02:58 +08:00
楼主没看仔细啊, JWT 除了前两段 header, payload 之外, 还有第三段: 签名
服务端签发 JWT 时, 会用自己的密钥(对称 /非对称皆可)生成一个签名, 收到 token 时只需要验签通过即认为合法, 而验签是一个无状态的过程.
Sparetire
2019-02-18 20:45:01 +08:00
你去游泳,他给你一个保险柜钥匙,你下次拿钥匙开保险柜,只认钥匙不认人
Lateautumn
2019-02-18 21:37:31 +08:00
@rayingecho 了解了,刚才又多找了写资料,我可以这么理解,就是使用签名来作为验证,具体用户可以根据 payload 里面的信息来找相关的用户
Lateautumn
2019-02-18 21:37:42 +08:00
@Sparetire 了解老哥,很形象
agagega
2019-02-18 22:45:47 +08:00
这样的优点也会带来一个缺点:签发出去的 Token 没法撤销
Esioner
2019-02-18 23:21:55 +08:00
@agagega 可以设置过期啊
runningman
2019-02-18 23:24:17 +08:00
@agagega 所以自己还得加一层 redis 存起来
xyz132
2019-02-18 23:49:31 +08:00
你可以把过期时间戳直接放在 JWT 里面
fleam
2019-02-19 08:13:12 +08:00
密匙比对
glaucus
2019-02-19 08:32:06 +08:00
借此想问一下各位老哥,可以再 payload 里放置过期时间来判断 Token 是否失效,但如果我要主动让用户 Token 失效,比如用户修改了密码需要重新登录,这种情况怎做呢?
90d0n
2019-02-19 08:36:26 +08:00
@glaucus #10 token 存 redis 里
lsongiu
2019-02-19 08:49:06 +08:00
其实我觉得如果 token 存 redis 里,为什么不直接用 uuid 呢
wizardoz
2019-02-19 09:31:48 +08:00
JWT 有签名机制,也就是说你把认证服务器的公钥配置在业务服务器,然后检验 JWT 是否为认证服务器签发的。如果确认了 JWT 确实为认证服务器签发,那么 jwt 的 payload 中携带的用户名、用户权限等信息都是可信任的。
chaleaochexist
2019-02-19 09:34:27 +08:00
@glaucus 增加黑名单.在做一次对比. 黑名单可以放到数据库里也可以放 redis.
lizhenda
2019-02-19 09:44:50 +08:00
业内普遍做法是放在 redis 里面,既可以实现单点登录又可以做设置密码重新生成
groot
2019-02-19 10:09:27 +08:00
@glaucus 我是给每个用户单独的 secret key,修改密码重置 secret key,token 也就失效了
rayingecho
2019-02-19 10:15:49 +08:00
@lsongiu
jwt 对 redis 是弱依赖,redis 挂掉只是被踢出的 token 可以正常使用,但不会影响正常的 token。
sessiom 共享对 redis 是强依赖,redis 挂了用户就无法鉴权
tabris17
2019-02-19 10:16:40 +08:00
当你用了 JWT 会发现有各种问题,然后还必须使用服务器端来维护 token,最后就变成和普通的 session 一样了
tabris17
2019-02-19 10:19:06 +08:00
@rayingecho 『被踢出的 token 可以正常使用』就已经是一个很大的安全隐患了,在强安全系统里是完全不可接受的,所以 token 必须在服务器端 redis 里验证一遍,这又跟 session 完全没区别了
libook
2019-02-19 10:33:17 +08:00
JTW 实现无状态的思路是把用户会话完全交给客户端来记录,所以需要服务端修改用户的会话状态的话,JWT 这种机制就不适用。

不过拿 JWT 来当 Cookie/Session 来用也未必不好,比如能比较方便得解决 Cookie 在各应用平台上实现的难题。

没有银弹,每种设计思路都有适合或不适合的场景,如果想最大程度享受无状态带来的好处,又希望有改密码踢出登录这种功能的话,可以把用户密码的 Hash 也存在 JWT 的 Payload 里,然后如果有人修改了密码就把这个用户 ID 和密码 Hash 放到各个服务的黑名单里,比如 Token 失效时限是 7 天,那么这个黑名单里的项目也可以在加入 7 天后自动移除,这样在预期极少数人修改密码的情况下可以做到尽可能无状态。这个方案稍微复杂一点的就是如何在弹性伸缩的服务集群中有效广播黑名单。

都是要看实际情况来设计的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/536256

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX