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

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

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

8563 次点击
所在节点    Python
66 条回复
yim7
2019-02-19 12:14:20 +08:00
现在用 jwt 存会话只是跟风
Kaiv2
2019-02-19 12:31:41 +08:00
安全性要求不高的场景,使用 JWT 确实方便。
abcbuzhiming
2019-02-19 12:41:57 +08:00
jwt 这东西无非就是把状态存储在客户端而已,如果你要灵活的保持随时踢出客户端的能力,JWT 就不合适,而且 JWT 的有效时间不能设太长,否则不安全,JWT 一旦签发就不能延期,也是一个问题
skypyb
2019-02-19 13:16:49 +08:00
https://github.com/skypyb/JwtBuilder-CryptographicComponent
我写的 JWT 建造工具,了解一下?:手动狗头
br00k
2019-02-19 13:30:29 +08:00
@abcbuzhiming 延期可以使用 refresh_token。
blue0125
2019-02-19 13:34:17 +08:00
@rayingecho #32 那请问下,session 的 更新机制,一般会在 jwt 实现么?每次接口返回新的 jwt,更新过期时间?
GTim
2019-02-19 13:34:30 +08:00
@passerbytiny 已经很全面了
gz911122
2019-02-19 13:34:51 +08:00
@skypyb 对比 jjwt 的优点是啥?
lolizeppelin
2019-02-19 13:45:08 +08:00
本质上是认为在不知道服务端加密 key 的情况下你无法伪造出合法 token,所以服务端只用对 token 和服务端的加密 key 进行运算就能判断 token 所带信息的真伪

和 session 对比最大优点是 token 的校验不需要读取存储设备,也不需要重新鉴权,高并发下优势很大
缺点是不能提前过期 token 以及在 token 过期时间内改变 token 的内容.

建议看下 fernet token 的的做法, 理解下 fernet token 为什么要轮询换加密
rayingecho
2019-02-19 13:53:54 +08:00
@blue0125
假如是可信的 client, 可以随着 acess token (jwt) 一起下发一个 refresh token
假如是不可信的 client, jwt 过期后(假如 payload 里设置了过期时间的话) 由 client 自己来做重新登录
rayingecho
2019-02-19 13:55:39 +08:00
@passerbytiny
请教一下, 在令牌里放授权会有什么问题? 之前某个系统的设计中我选择直接将 authority 存储到 jwt payload 增大网关层吞吐量
lolizeppelin
2019-02-19 14:07:08 +08:00
@rayingecho
就是无法撤销无法更新呗,表面上你可以通知客户端换 token,但这只对正常处理的客户端有效啊,别人非要保留之前的 token 继续拿来用,服务端也认为是合法的

比较好的做法是不重要授权信息直接存 token 的 playload,重要的还是得存在服务端每次校验

或者 xx 次操作后重新读取授权信息
skypyb
2019-02-19 14:12:34 +08:00
@gz911122 没有优势,只是能用 ( 硬是要说,就是小吧...
passerbytiny
2019-02-19 14:13:28 +08:00
@rayingecho #47 JWT 是弱加密,容易被人反向工程。当然你这个方式是为性能优化的,没啥问题。
rayingecho
2019-02-19 14:21:57 +08:00
@lolizeppelin
是的, jwt 本身无法撤销无法更新. 我在实践中采取的办法是增加一个校验层(这里会引入状态, 不过权衡在 #21 说过了).
简化后的大体逻辑是每个 jwt 的 payload 里加上一个 uuid, 通过 redis 做黑名单, 假如某个 uuid 在 redis 里存在, 表明这个 jwt 已经被撤销了
重新授权, 修改密码, 多端登录等场景都会触发撤销
rayingecho
2019-02-19 14:26:31 +08:00
@passerbytiny
理解了.
不过我之前的认知是对不可信 client 发放的 jwt 只要用 RSA256 并且直接拒绝在 header 中声明其他所有加密算法的 token 应该是足够安全的, 这里面有什么门道吗?
passerbytiny
2019-02-19 15:16:35 +08:00
@rayingecho #52 我又特意去看了一下,JWT 的 Header 和 Payload 是 Base64Url 编码,即明文,你要是放授权那就相当于把授权配置明文公布出去了。如果别人猜出来了签名密钥,原来只能伪造认证,现在还能伪造授权。

到这里我要纠正我之前的结论了,因为 Payload 是明文的,所以单靠 JWT 自身,是不能完美解决可以被复制的漏洞的。
rayingecho
2019-02-19 15:21:22 +08:00
@passerbytiny
是的, 反向出密钥就 GG 了, 不过非对称加密无法(在合理时间内)破解是 https 和区块链的基石啊...
lolizeppelin
2019-02-19 15:31:51 +08:00
@rayingecho

token 就是要避免 io,你这个做法只是 io 的数据量少了,但是 io 还存在,而且全压在 redis 上

如果你授权数据量少请求次数频繁的话, 授权内容放 token 还是放 redis 里 io 机几乎不多(都开销再网络上了)
lolizeppelin
2019-02-19 15:36:06 +08:00
@passerbytiny

Payload 加密不加密都可以的, 取服务端 token 密钥或密钥前 xx 位用来加密 Payload 就完事

服务端密钥不被反向出来才是最重要的,所以有了 fernet token 的做法避免长时间的用一个 key 去生成 token 降低密钥被解出来

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

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

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

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

© 2021 V2EX