每月一争, 为什么 JWT 这么多诟病, 什么下线设备登录 JWT 不是很容易解决吗?

2023-06-19 12:13:04 +08:00
 SethShi

JWT 的基本就不再过多阐述

思考的问题前提: 比如我们面对一个千万级用户的系统. * 客户端需要和服务端交互, 假设 50% 的接口需要校验 * 10% 的接口需要获取个人信息


至于常见的 JWT 诟病解决方案

为什么要用 JWT ?

下线, 黑名单为什么不直接存储 token ?

6472 次点击
所在节点    问与答
55 条回复
SethShi
2023-06-19 12:16:45 +08:00
还有 access_token 一个就够了, 为什么还要有 refresh_token, 除了官方说的安全之外, 就是可以作为两个时间点去使用.
access_token 每次都要校验, 可以简单的校验, refresh_token 使用的频次比较少, 这时候可以做更完整的校验.
LeegoYih
2023-06-19 12:42:44 +08:00
用了 JWT 还要存 token 到服务端,每次还要查版本号和黑名单,不是脱裤子放屁吗?
用户权限之类的更新了怎么办?难道让用户退出重新登录一遍吗?
查一次缓存就能解决的事情,不要太小看 Redis 的性能了。

而且 JWT 不是 100%安全的: https://github.com/yihleego/jwtcrack
oldshensheep
2023-06-19 12:53:10 +08:00
你这个都依赖 **分钟级别过期 access_token**

你加个 token_version 那每次刷新 jwt 就要查询数据库,而且你刷新的非常频繁,这不又和原来一样
同样的还有检查 device_id 要查询数据库
giter
2023-06-19 12:56:45 +08:00
我选择把 accessToken 与 refreshToken 存在 localStorage 中。既然要 JWT ,那就贯彻到底,给服务端彻底减负。
nomagick
2023-06-19 13:03:20 +08:00
jwt 真正的用途在于验证其他站点的用户和 token ,而不是自己站点的。
不要为了用而用。
ztxcccc
2023-06-19 13:08:16 +08:00
别查库了谢谢
amlee
2023-06-19 13:13:02 +08:00
jwt 的设计初衷就是要无状态,如果你的需求必须要求有状态,那么 jwt 的设计不适合你,为什么不用现成的 session 方案?
这本质上是一个需求和设计是否匹配的问题,搞清问题本质,跟技术优劣,或者说能否给技术打补丁以满足需求没关系。
板砖和锤子都能敲钉子,你非要说我能打磨一个完美的板砖去敲钉子,那我只能说脑子有包
gogola
2023-06-19 13:17:22 +08:00
@LeegoYih #2
暴力破解这玩意,不好说。
CodeCodeStudy
2023-06-19 13:21:13 +08:00
token 存 redis 不就完事了?
emric
2023-06-19 13:21:29 +08:00
我这边用 last_login ,日期不相同就拒绝。
感觉你说的大部分问题,都是修改以下 last_login 就行。
SethShi
2023-06-19 13:24:49 +08:00
@LeegoYih 我就问一下, 你使用 token 权限更新了怎么办? 这个和 jwt 没关系. 你权限更新其它方式该怎么做就怎么做. 不是我小看, 而是如果还不消耗存储, 不消耗 io 的方式为什么不讨论呢?

@oldshensheep token 的方式, 按用户级别来说, 每次请求来都查 redis, 并且 jwt 包含千万级别的用户数据, 而刷新的时候查询, 减少了 90% 的请求, 并且 redis 的存储只用非常少
@giter 没错了, 那肯定都要存客户端的, 和我说的没区别
@nomagick 你在哪看的定义? 你说的是 oauth2 吧
@ztxcccc 举个栗子
@amlee 又来一个不看解决方案, 上来就说不查库的
SethShi
2023-06-19 13:26:01 +08:00
@CodeCodeStudy 话说不看场景直接就存?
@emric 原理方案差不多的, 总是有些人在说为什么不存 redis 呢. 所以要讲这个东西.
ellermister
2023-06-19 13:33:45 +08:00
那每个 jwt 请求到服务端不都是要查一下有没有在 redis 黑名单列表里,千万级的用户也是千万级的查询啊,jwt 只是把 redis 存储大小改了,没改变查询次数。
@seth19960929
SethShi
2023-06-19 13:33:57 +08:00
@LeegoYih 我看了两眼你这个代码, 上来来个碰撞代码就说不安全, 能拿出具体的文献出来吗.
按你这样子说, 世界上没有安全的加密, 我只要写一个碰撞代码, 它们安全只是我现在没有碰撞到, 不代表我做不到.
SethShi
2023-06-19 13:39:22 +08:00
@ellermister 嗯嗯, 这是一个讨论帖子.
两种方案:
1. 只在刷新 token 的时候才查询是否在黑名单, 请求可以降低非常多, 有个问题就是会有延迟, 比如 5 分钟刷新一次 token, 那么就会加入后有 5 分钟延迟. 如果是部分场景完全可以用这种(只要 app 左右逻辑处理, 能及时失效, 如果有人窃取了 token, 那么它也只能使用 5 分钟, 到期了刷新就会得知被加入黑名单)
2. 大小还是差别很多的. 往 redis 里存 32 位字符串 key 1000w 个看看. 我等会给一个答案
LeegoYih
2023-06-19 13:45:57 +08:00
8355
2023-06-19 14:00:50 +08:00
只用 jwt 没有防御措施绝对是错误的行为

单 ip 连续请求错误 token 值为不可信行为,这是风控策略应该做的事
在敏感操作必要时进行密码检查

仅传入 token 就给予最大用户操作权限本身就不合理
shakaraka
2023-06-19 14:01:36 +08:00
你说得对
Masoud2023
2023-06-19 14:04:19 +08:00
你文中的黑名单和单台设备下线,归根结底都是要去查库,那用 jwt 和不用 jwt 做 sessionid 有什么区别么
SethShi
2023-06-19 14:05:57 +08:00
@LeegoYih
只要循环结束, 我一样能破解呀.

for ($i = 1; $i < pow(32, 16); $i++) {
$key = genKey($i);
$result = openssl_decrypt(hex2bin('1fbf2605f954fad3ba18115000735aee'), 'aes-128-cbc', $key, 1, '0000000000000000');
}

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

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

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

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

© 2021 V2EX