单设备登录实现方案
要实现单设备登录,需设立一种机制,确保同一账号在不同设备上不能同时保持活跃。从前端角度来说,常见的实现方式主要有两种:
1. 基于 Token 版本控制(推荐)
1.1 核心思想
Token 版本号(token_version)充当唯一凭证,每次新设备登录时,版本号 +1,旧 Token 失效。此机制通过对 Token 版本的精确管理,使得服务器能够准确判断当前请求的合法性,有效保障单设备登录的安全性和稳定性。
1.2 流程拆解
用户首次登录
- 用户登录后,数据库中的 token_version 设为 1。这一步骤为后续的版本控制奠定基础,明确了初始状态。
- 后端生成 JWT Token,并在 负载(payload) 中加入 {userId: 1, tokenVersion: 1}。JWT Token 作为用户身份验证的关键凭证,包含了用户 ID 和当前的 Token 版本信息,确保身份验证的准确性和完整性。
- 返回 Token 给前端,前端存储在 localStorage 或 请求头字段(Authorization )中。前端妥善存储 Token,以便后续请求中携带,实现用户身份的验证和识别。
用户在新设备登录
- 新设备登录后,后端查询该用户的 token_version,然后 +1,更新到数据库(如 token_version = 2)。后端通过查询和更新操作,确保数据库中记录的 Token 版本始终是最新的,为后续的验证提供准确依据。
- 生成新的 Token {userId: 1, tokenVersion: 2},返回给新设备。新的 Token 携带了更新后的版本信息,保证新设备登录的合法性和有效性。
旧设备携带 Token 访问接口
- 旧设备的 Token 仍然是 {userId: 1, tokenVersion: 1},但数据库中 token_version = 2。由于版本不一致,旧设备的 Token 已无法通过验证。
- 服务器验证 Token,发现 tokenVersion!== 数据库的 token_version,返回 401,拒绝访问。服务器通过严格的验证机制,确保只有合法的 Token 才能访问接口,保障系统的安全性。
旧设备强制下线
- 旧设备前端收到 401 响应后:
-
- 清除本地 Token,确保本地不再保存已失效的凭证。
-
- 跳转到登录页,引导用户重新进行登录操作。
-
- 提示 "账号已在其他设备登录,请重新登录",向用户清晰解释下线原因,提升用户体验。
该方案核心是维护了 token_version 的版本值,是实现单设备登录最简单的方案。通过简洁的版本控制逻辑,有效实现了单设备登录的功能,降低了开发和维护的难度。
2. 基于 WebSocket 的实时强制下线
2.1 核心思想
每次用户在新设备登录时,服务器通过 WebSocket 通知旧设备下线,旧设备收到消息后清除 Token 并强制登出。此方案利用 WebSocket 的实时双向通讯特性,实现了对旧设备的即时下线控制,极大提升了用户体验和系统安全性。
2.2 流程拆解
用户首次登录
- 用户登录后,服务器建立 WebSocket 连接,并在 Redis 或者数据库中存储对应状态,如:{userId: 1, socketId: "xm123"} 以记录该设备的 WebSocket 连接 ID。服务器通过建立连接和存储状态,为后续的实时通讯和设备管理提供了基础。
用户在新设备登录
- 新设备登录后,服务器检测到该用户已有活跃连接。服务器通过实时监测,能够及时发现同一用户在不同设备上的登录行为。
- 给旧设备发送 WebSocket 消息:"你的账号已在其他设备登录,请重新登录"。通过发送明确的通知消息,告知旧设备用户账号的异常登录情况。
- 删除旧设备的 WebSocket 连接记录,确保系统中只保留当前活跃设备的连接信息。
- 新设备建立 WebSocket 连接,存储 {userId: 1, socketId: "xm456"}。新设备成功建立连接并存储相关信息,保证后续通讯的顺畅。
旧设备收到 WebSocket 消息
- 旧设备监听到 "被踢下线" 消息:
-
- 清除本地 Token,确保本地不再保存已失效的凭证。
-
- 自动跳转到登录页,引导用户重新进行登录操作。
-
- 提示 "账号已在其他设备登录",向用户清晰解释下线原因,提升用户体验。
与基于 Token 版本控制相比,此方案核心是利用了 WebSocket 双向通讯的能力来实现强制下线的功能,好处是可以做到即时响应,麻烦的地方是需要重新对接 ws 协议,增加了开发和维护的复杂性。
3. 两种方案差异对比
| 方案 | 优势 | 劣势 |
|---|---|---|
| 基于 Token 版本控制 | 逻辑简单,后端维护 Token 版本即可,兼容性好 | 需要前端主动处理 401,可能有短暂的延迟 |
| 基于 WebSocket 实时强制下线 | 即时性强,用户体验更好 | 需要 WebSocket 连接,维护连接状态,断连时需要额外处理 |
4. 方案结合使用
可以以 WebSocket 优先,当 WebSocket 连接异常时,后端回退到 Token 版本校验。这样既能保证即时强制下线,也能兼容不支持 WebSocket 的场景。在实际应用中,根据用户设备和网络环境的不同,灵活切换验证方式,确保系统的稳定性和用户体验。例如,在网络环境较好、设备支持 WebSocket 的情况下,优先使用 WebSocket 实现即时下线;而在网络不稳定或设备不支持 WebSocket 时,自动切换到 Token 版本校验,保障系统的正常运行。同时,还可以在系统中加入日志记录功能,对每次登录和下线操作进行详细记录,以便后续的问题排查和数据分析。