如题,现在登录,我使用了 JWT 机制,但是怎么防止一个用户,在多个设备上登录呢?
1 angel001ma 2024-03-15 15:11:34 +08:00 搜索单点登陆 |
![]() | 2 OutOfMemoryError 2024-03-15 15:12:29 +08:00 ![]() @angel001ma #1 单点登录指的是在单个站点登录后同步其他站点的登录状态,不是防多端登录用的吧 |
![]() | 3 996635 2024-03-15 15:14:48 +08:00 防止多端登录和 JWT 没关系, 后端维护 token 的生效状态即可 |
![]() | 4 liuhan907 2024-03-15 15:15:01 +08:00 jwt 就是为了给你多端登陆用的,你现在要防止。 |
![]() | 5 yrzs 2024-03-15 15:15:13 +08:00 将 jwt 存入 redis,判断 token 是否是 redis 里的 |
![]() | 6 Akitora 2024-03-15 15:15:16 +08:00 感觉 JWT 就主打一个无状态,在服务端和客户端都再额外维护一个状态绑定设备有点怪怪的 |
![]() | 7 Helios0 2024-03-15 15:16:31 +08:00 JWT不支持,本身就是面向离线的设计,你说的这个场景是 session 。 |
8 NessajCN 2024-03-15 15:16:38 +08:00 jwt 只是个验证工具,对于用户的登录端的限制需要你自己写 session control 因为很显然,你要防止用户多端登录,首先需要服务端知道用户已经登录 |
![]() | 9 fengzhongdeyihan 2024-03-15 15:18:50 +08:00 返回 jwt token 之前绑定 uid 和 token 到 redis 中. 然后校验的时候拿 jwt 的里面的 token 和 redis 里面的 token 对比. |
![]() | 10 tonywangcn 2024-03-15 15:19:17 +08:00 签发 jwt 时,把 session id 放到 token 中 |
11 0o0O0o0O0o 2024-03-15 15:19:45 +08:00 via iPhone ![]() 有状态与 JWT 在本站能不能算排名前十的技术争论主题? |
12 fkdog 2024-03-15 15:19:56 +08:00 jwt 关联设备 id ,设备 id 可以直接存在 jwt 里或者服务端存储,检测到请求对应的设备 id 与签发 jwt 的设备不一致则直接拒绝访问。 |
![]() | 13 shakaraka PRO ![]() 你这是有状态的需求。明显是不符合 JWT 的使用逻辑强上。 |
14 thinkershare 2024-03-15 15:21:28 +08:00 JWT 不支持你这个功能,你不应该使用 JWT 维护用户的 SESSION. |
![]() | 15 javalaw2010 2024-03-15 15:22:24 +08:00 防止不了,jwt 本身是无状态的协议,你要防止多端登录,就必须记录 token ,此时 jwt 就退化为 session 了,所以我一直觉得目前的风气有点滥用 jwt ,所以我新项目中的都使用最简单的随机字符串作为 token 了,所谓返璞归真吧。。。 |
![]() | 16 cat 2024-03-15 15:22:53 +08:00 @0o0O0o0O0o 能,我发现很多人没懂 jwt 到底是啥意思 干嘛的,一味的想用来取代 session |
![]() | 17 lonenol 2024-03-15 15:32:54 +08:00 你想想用传统的 cookie session 怎么防止多端登录呢? |
19 EasyProgramming 2024-03-15 15:40:49 +08:00 1.使用手机号生成 jwt 字符串 2.用户登陆后,使用手机号作为 key ,jwt 字符串作为 value ,存入 redis ,将 jwt 字符串作为 token 下发给用户 3.用户访问时,后端解析用户传入的 jwt 字符串( token ),拿到手机号后,使用手机号去 redis 查询对应的 jwt 字符串,校验是否和一致 以上三步,可以实现你的需求 |
20 Biluesgakki 2024-03-15 15:41:02 +08:00 确实很奇怪 不过要实现就把 token 放 redis 就行 上线的时候强行把原来有的踹了 |
![]() | 21 HarrisonLee 2024-03-15 15:41:12 +08:00 既然你这样问了,那么普通 token 也适合你,为什么要使用 jwt ? |
22 crazyweeds 2024-03-15 15:54:13 +08:00 如果你要防止,那么就不能用这种无状态方案。 当然,现实中能够见到不少用 JWT 然后又限制单个设备登录的傻缺方案,他们又维护了这个 token ,搞笑。 如果你这个特性是硬性要求,综合用户体验,可以考虑分布式 session 共享方案,或者自己用 http header + token 实现一套,更简单有效。。 |
23 imokkkk 2024-03-15 17:01:04 +08:00 加一层 Redis |
![]() | 24 joker8ren 2024-03-15 17:02:15 +08:00 要么 session 要么放 token 做检测 |
25 Yukineko 2024-03-15 17:09:49 +08:00 直接换成 session |
![]() | 26 hideon 2024-03-15 17:10:34 +08:00 JWT 设计用于无状态的,单端登录回归有状态,请在服务端自行记录登录状态 |
27 type 2024-03-15 17:13:04 +08:00 那就没必要使用 JWT |
![]() | 28 siweipancc 2024-03-15 20:52:41 +08:00 via iPhone 回退到 session 设计,这是个永恒的话题哈哈哈,无解的。最大的作用也就是解决了某些人的 cookie 焦虑而已。 |
![]() | 29 rekulas 2024-03-15 21:21:22 +08:00 加个中间件就行了, 验证的时候都要过一遍,有些人直接用的服务器,有些人用的 redis 集群 楼上一些觉得不该用 jwt 的可能过于理想化了, 因为现在很多系统都基于 jwt 概念验证而开发, 你接手后因为自身业务需求想限制登录, 没必要去把整个 jwt 换掉,这样改动工作量会比较大而且可能引来未知的 bug(因为 jwt 不仅仅代表登录有些系统可能还用来传递权限之类), 只需要入口或中间层加验证就行了, 改动是最小的, 我们之前系统就有这样的需求 |
30 BEza5k2j7yew0VN9 2024-03-16 01:11:33 +08:00 在新设备登录时创新的 token ,吊销旧 token ,服务端只允许一个 token 存在 |
![]() | 31 lilei2023 2024-03-16 07:49:22 +08:00 @angel001ma 这和单点登录有啥关系?误人子弟! |
![]() | 32 demonzoo 2024-03-16 09:37:26 +08:00 这种场景就别用 jwt 了吧,用 session |
![]() | 33 me1onsoda 2024-03-16 09:40:42 +08:00 设计的人是个二把刀 |
34 cndenis 2024-03-16 09:58:39 +08:00 ![]() 用啥技术都是为了符合需求的, JWT 和 session 机制同时用也不代表就不合理. 比如说普通浏览仅验证 JWT, 在关键操作中才验证 session, 在某些场合中也是可行的嘛, 为啥非要冷嘲热讽呢 |
35 ic3z 2024-03-16 10:03:02 +08:00 via iPhone 登录生成 token 的时候看用户有没有别的有效 token ,有的话把原先的 token 清空。 要配合 jwt 验证机制。 |
![]() | 36 R4rvZ6agNVWr56V0 2024-03-16 10:31:22 +08:00 最简单的做法是使用用户状态,在用户登录时,将用户状态(如“已登录”)存储在服务器端。每次用户发起请求时,服务器都会检查用户状态。如果用户状态为“已登录”,但请求中的 Token 与服务器中的 Token 不匹配,说明用户可能在另一个设备上登录,可以拒绝该请求 |
![]() | 37 zhongjun96 2024-03-16 10:37:31 +08:00 @yrzs #5 这样 jwt 就没意义了,不如直接一个 uuid-token |
38 Azure99 2024-03-16 10:57:00 +08:00 jwt 本身就是为了无状态设计的,你要是服务端再维护一个状态,和 session 有什么区别? |
![]() | 39 hidemyself 2024-03-16 11:15:37 +08:00 不适合用 jwt,改造一下 |
![]() | 40 yogogo 2024-03-16 11:33:46 +08:00 你应该是维护一个用户的 token 关联登陆设备信息,每次登陆后,关联 token 跟登陆设备信息,然后请求使用的时候检查使用 token 的设备是不是跟登陆设备信息一样 |
41 sherryqueen 2024-03-16 11:52:53 +08:00 jwt 本身是无状态的~. 不过你真想做, 就走了 cookie-session 那套了. 需要后端来维护 jwt 的状态了. 脱离了 jwt 本身的意义.. 一般推荐就是将 jwt 的过期时间调低~ |
42 xylophone21 2024-03-16 12:05:00 +08:00 你如何定义多端登录?至少在上面的讨论中看到过两种定义 1.用第三方的客户端多端登录,别说 jwt ,即使是 session ,你也拦不住对方多端交换 sessionid/token ,然后把这些塞到 HTTP 头里。除非你每个接口都刷新,但这样万一失败一次,登录就被踢了,体验恐怕很难做好。 2.用你的客户端,浏览器多端登录。那把客户端 Id 塞到 JWT 不就可以了 |
43 xylophone21 2024-03-16 12:27:54 +08:00 不好意思,写到一半想岔了,目标是防止多端登录,写着写着想成了如何实现多端登录。 第一种情况不变,第二种情况下实际上就变成了第二个端登录时,如何吊销第一个端的 JWT ?好了标准答案来了,标准的 JWT 不支持提前吊销。那怎么办?当然是非标准的 JWT ,比如前面提到的把 JWT 存到 Redis ,以及如果你更多的搜一下可以找到的优化方案--只存吊销列表的布隆等 |
![]() | 44 ns09005264 2024-03-16 12:40:40 +08:00 我觉得,jwt 最大的意义是自带信息。 生成 jwt token 的时候除了必要的用户信息外,还可以加上登录时的设备信息,比如 ip 、user-agent 或其他识别信息等。这样 jwt token 里就包含设备信息了。 后续验证 jwt token 时,看它的请求头里和 jwt token 包含的信息是否对应得上,对不上就是多端使用 jwt token 了 比如该用户在 PC 浏览器上登录了,服务器为此生成了 jwt token ,这个 token 中包含的 user-agent 是 pc 的。 后面该用户把 jwt token 复制到 Android 浏览器上用来使用,但是请求头中的 user-agent 和 jwt token 里的对应不上,那么就是异端登录了。 |
45 yannxia 2024-03-16 12:43:23 +08:00 原来怎么做,现在就怎么做,Session 分了一个 ID ,JWT 你也可以。没什么区别 |
![]() | 46 ns09005264 2024-03-16 12:56:51 +08:00 https://gateway.pinata.cloud/ipfs/QmWv2NmD5iLVTsSo3QkEsGnHKxtQqMoeZZTs76ohGz1aHC 图里这个 jwt token 是在 linux 下 firefox 中登录时生成的,如果用户把这个 token 拿到 windows 上的 chrome 去用,只需要获取请求头中的 user-agent 就可以判断它是异端登录。整个过程依旧是无状态的,根本不需要在服务器的什么地方维护用户的登录和设备信息。 |
![]() | 47 Glkcv 2024-03-16 13:34:08 +08:00 建议别用 jwt |
![]() | 48 FYFX 2024-03-16 13:36:11 +08:00 @ns09005264 #46 依赖 ua 就不太靠谱吧 |
![]() | 49 hafuhafu 2024-03-16 13:47:59 +08:00 还是要在服务端维护状态进行判断。JWT 本身是无状态的,并不代表它一定要用在完全无状态的场景,可以当成本身就是一个编码过的字符串,里面有信息而已,完全可以继续用。 |
![]() | 50 akagishigeru 2024-03-16 13:52:01 +08:00 @angel001ma 兄弟别误人子弟,这叫单端登录,单点其实是全端登录 |
![]() | 51 ns09005264 2024-03-16 14:00:55 +08:00 @FYFX 只是用 user-agnet 举个例子,不想那么严格的时候可以根据 user-agent 来判断,只要别在验证不通过时明确告知原因就能阻挡一部分非法请求。想严格一点可以用浏览器指纹或设备 id 之类的。总之这是多设备识别的时间,有状态的 sessionID 能做到的,无状态的 jwt token 也能做到。 |
![]() | 52 skull 2024-03-16 18:02:59 +08:00 via iPhone @angel001ma 原来你是这么字面理解的啊 |
53 Plutooo 2024-03-17 00:57:36 +08:00 看到 11 楼笑出声 |
![]() | 54 Zy143L 2024-03-18 00:39:26 +08:00 是想设计成挤号还是禁止多登陆呢 挤号的话就存 JWT 判断提交的是否和库里面的一样就行了 |
![]() | 55 yrzs 2024-03-20 09:41:44 +08:00 @zhongjun96 确实没意义 但是强行改 jwt 这样最方便 |