在使用腾讯QQ进行登录操作时,用户可能会注意到其独特的登录机制:用户可以在手机和电脑上同时保持在线状态,但无法在两个手机设备上同时登录同一个账号。
所谓同端互斥登录,其核心规则是:类似于腾讯QQ的登录方式,在同一类型的设备上只允许单一地点的登录,而在不同类型的设备上则支持同时在线的功能。
动态演示图:
同端互斥登录
Sa-Token 是一款专为Java开发设计的轻量级权限认证框架,其主要功能在于解决登录认证、权限验证、单点登录、OAuth2以及微服务网关鉴权等一系列与权限管理相关的问题。
本文将详细阐述在 Sa-Token 框架中,如何实现以下几种登录策略:
- • 单地登录:这一策略要求一个账号在同一时间内只能在一个地点登录,新登录的请求将会取代旧的登录会话,这一策略也被称为单端登录。
- • 多地登录:与单地登录相对,多地登录允许一个账号在同一时间内可以在多个地点同时登录,新旧登录会话可以共存,这一策略也被称为多端登录。
- • 同端互斥登录:该策略规定在同一类型的设备上只允许单一地点登录,而在不同类型的设备上则允许同时在线,这一模式与腾讯QQ的登录机制相似,即手机和电脑可以同时在线,但两个手机设备不能同时登录。
针对注销操作,Sa-Token 也提供了多种策略:
- • 单端注销:此策略仅注销被调用退出操作的那一端。
- • 全端注销:当一端执行注销操作时,所有登录该账号的设备都会被下线。
- • 同端注销:此策略允许选择性地注销某一类型的设备,例如所有手机端,而电脑端则不受影响。
在 Sa-Token 中,多地登录模式是其默认的登录策略,这种模式相对简单易用。
注:如果你正在使用 SpringBoot 3.x 版本,只需将 sa-token-spring-boot-starter 更新为 sa-token-spring-boot3-starter 即可。
启动类配置:
在上述代码示例中,当多个用户尝试登录同一账号时,系统不会对旧的会话进行任何处理,这意味着同一账号可以在多个地点同时登录,且各登录会话之间不会相互干扰。
调用注销方法后,当前账号的所有登录端将同时被下线。
若需仅注销某一端,可以在配置文件中将 is-share 的值设置为 false。
is-share 配置项的含义在于:当多个用户登录同一账号时,是否应该共享一个 Token。
- • 当该值为 true 时,所有登录会话将共享同一个 Token。
- • 当该值为 false 时,每次登录都会生成一个新的 Token。
在将 is-share 的值设置为 false 后,每次登录都将返回一个不同的 Token,相应地,调用 StpUtil.logout() 方法也只会注销当前的 Token,而不会影响其他登录会话。
实现单地登录的关键在于修改 yml 配置文件:
is-concurrent 配置项的含义是是否允许同一账号进行并发登录:
- • 当该值为 true 时,允许账号在多个设备上同时登录。
- • 当该值为 false 时,新登录会取代旧的登录会话。
除 is-concurrent 配置项外,其他代码与多地登录模式相同。当用户在两个不同的浏览器中分别登录同一账号时,如果旧会话再次尝试访问系统,将会收到如下提示信息:
在单地登录模式下,注销策略的问题并不存在,因为同一时间内,一个账号最多只能在单一设备上在线。因此,只要调用注销操作,就必然会导致全端下线。

至此,我们将重点介绍同端互斥登录策略,这一策略能够让系统像腾讯QQ一样,在同一类型的设备上实现单地点登录,而在不同类型的设备上则支持同时在线。
那么,在 Sa-Token 中如何实现同端互斥登录呢?
首先,与单地登录模式相同,需要在配置文件中将 sa-token.is-concurrent 设置为 false。然后,在调用登录等相关接口时,需要声明设备标识:
通过调用上述方法进行登录后,同一设备上的其他登录会话将被强制下线(不同设备上的登录会话不受影响)。当再次访问系统时,将会抛出 NotLoginException 异常,其中场景值被设置为 -4。
场景值的具体含义如下:
-1NotLoginException.NOT_TOKEN:未能从请求中读取到 Token。-2NotLoginException.INVALID_TOKEN:已读取到 Token,但该 Token 无效。-3NotLoginException.TOKEN_TIMEOUT:已读取到 Token,但该 Token 已经过期。-4NotLoginException.BE_REPLACED:已读取到 Token,但该 Token 已被其他会话顶下线。-5NotLoginException.KICK_OUT:已读取到 Token,但该 Token 已被踢下线。
如果第二个参数设置为 null 或不填写,则表示将所有在线的该账号会话进行踢下线操作。被踢下线的用户在再次访问系统时同样会抛出 NotLoginException 异常,场景值将被设置为 -5。
如果在登录时没有指定设备类型值,系统将返回一个默认值 default-device。
业务场景举例:假设用户希望通过手机端控制电脑端下线,而手机端本身不受影响。
在调用 logout 方法时,如果不填写具体的设备端类型,系统将默认执行所有端同时下线的操作。
以上内容详细介绍了 Sa-Token 框架在处理登录问题时的多种策略,无论是简单的多地登录还是复杂的同端互斥登录,Sa-Token 都提供了完善的解决方案。