同端互斥登录技术选型之Sa-Token(上篇)

devtools/2024/11/18 10:07:29/

文章目录

    • 同端登录冲突检测
      • 需求分析
      • 方案设计
        • 1、账号冲突检测策略
        • 2、实现思路
      • Sa-Token 入门
        • 入门 Demo
        • Sa-Token 实用功能
        • Sa-Token 原理

同端登录冲突检测

需求分析

在多用户系统中,如电商平台、企业办公系统或社交应用,用户的账户安全和系统的正常使用至关重要。

如果同一个账户同时在多个设备上登录,可能由于之前在别的地方临时登录后忘记退出账号,导致数据泄露或账户被滥用等问题。此外,还有可能会导致数据不一致问题,例如重复提交订单、聊天记录不同步等。

针对我们会员制的刷题网站,若会员账户被不法分子售卖或多人共享,将会损害公司利益。

为了防止这些情况,我们的系统需要能够实时监控和检测同一账户在多个设备上的登录情况,在检测到冲突时,及时通知用户并采取相应的安全措施(如强制下线或警告)。

方案设计

1、账号冲突检测策略

常见业务上有 3 种冲突检测策略:

1)单点登录模式

同一时间,只允许同一账户在一个设备上登录。即每次新设备登录时,检测当前账户是否已经在其他设备上登录,若已登录则将其他设备强制下线。

一般应用于企业内部系统或包含敏感数据的系统中。

2)多设备登录限制

允许同一账户在多个设备上登录,但需限制设备数量(如最多两台)。即每次登录时,检测当前账户已登录设备数量,若超过限制,系统阻止登录或强制最早登录设备下线。

这种模式常见于视频网站、买断制 / 订阅制软件。

一个软件激活码只能同时在 X 台设备使用,也是类似的机制。

3)同设备类型限制

允许同一账户在不同设备类型(如手机和 PC)上同时登录,但同一类型设备只能登录一个。例如,用户可同时在电脑和 iPad 上使用我们的平台,但不能在两台手机上登录在线。(QQ 就是这样)

要想实现这种策略,需要记录账户登录设备的类型,每次登录时检查是否有同类设备已登录,如果有则强制下线相同设备类型的旧登录。

这种策略常应用于一些需兼顾多端体验的应用。比如我们的面试刷题平台用户,经常有 iPad 和电脑端同时刷题的需求,因此我们采用第 3 种策略 同设备类型限制(同端互斥登录)。

2、实现思路

如何实现同端互斥登录呢?

  1. 用户登录时获取当前设备信息(通过 User-Agent 获取)
  2. 将用户登录信息与设备信息一起保存(本地或三方缓存中)
  3. 用户登录时判断同设备是否已经登录(本地或缓存中是否已存在)
  4. 如果检测到冲突,可以直接顶号(将前一个设备下线,也就是移除登录态)

其实自主实现这个需求也并不难,但涉及到登录这样的核心业务场景,经验不足的情况下,更建议使用一些成熟的第三方框架。比如轻量级 Java 权限认证框架 内置了 同端互斥登录功能,可以更快更稳地实现。

以下为 Sa-Token 同端互斥示意图:

借这个场景,带大家学习下 Sa-Token 框架。

Sa-Token 入门

Sa-Token 是一个轻量级 Java 权限认证框架,主要解决:登录认证、权限认证、单点登录、OAuth2.0、分布式Session会话、微服务网关鉴权等一系列权限相关问题。

Sa-Token 功能一览:

在这里插入图片描述

Sa-Token 旨在以简单、优雅的方式完成系统的权限认证部分,以登录认证为例,只需要一行代码:

// 会话登录,参数填登录人的账号id 
StpUtil.login(10001);

无需实现任何接口、无需创建任何配置文件,只需要这一句静态代码的调用,便可以完成会话登录认证!

如果一个接口需要登录后才能访问,我们只需调用以下代码来检测该用户是否已经登录:

// 校验当前客户端是否已经登录,如果未登录则抛出 `NotLoginException` 异常
StpUtil.checkLogin();

由于是国人开发,它的官方文档](https://sa-token.cc/doc.html#/) 写得非常通俗易懂,是纯天然的教程,基本上按照文档的顺序阅读一遍,就能够上手了。下面我们就先试着 参考文档 来运行下官方的 Demo。

入门 Demo

在 Spring Boot 项目中,可以通过sa-token-spring-boot-starter 快速引入 Sa-Token。注意版本:

<!-- Sa-Token 权限认证 -->
<dependency><groupId>cn.dev33</groupId><artifactId>sa-token-spring-boot-starter</artifactId><version>1.39.0</version>
</dependency>

Sa-Token 支持通过配置定制框架的行为,比如登录态过期时间、不活跃自动下线等:

server:# 端口port: 8081############## Sa-Token 配置 (文档: https://sa-token.cc) ##############
sa-token: # token 名称(同时也是 cookie 名称)token-name: satoken# token 有效期(单位:秒) 默认30天,-1 代表永久有效timeout: 2592000# token 最低活跃频率(单位:秒),如果 token 超过此时间没有访问系统就会被冻结,默认-1 代表不限制,永不冻结active-timeout: -1# 是否允许同一账号多地同时登录 (为 true 时允许一起登录, 为 false 时新登录挤掉旧登录)is-concurrent: true# 在多人登录同一账号时,是否共用一个 token (为 true 时所有登录共用一个 token, 为 false 时每次登录新建一个 token)is-share: true# token 风格(默认可取值:uuid、simple-uuid、random-32、random-64、random-128、tik)token-style: uuid# 是否输出操作日志 is-log: true

对于入门 Demo,我们可以不写配置,直接零配置启动项目。

然后我们编写 2 个测试接口,一个用于登录,一个用于检测是否已登录:

/*** 测试 Sa-Token 框架实现用户登录*/
@RestController
@RequestMapping("/test/user/")
public class TestSaTokenLoginController {// 测试登录,浏览器访问: http://localhost:8101/api/test/user/doLogin?username=zhang&password=123456@RequestMapping("doLogin")public String doLogin(String username, String password) {// 此处仅作模拟示例,真实项目需要从数据库中查询数据进行比对if ("zhang".equals(username) && "123456".equals(password)) {StpUtil.login(10001);return "登录成功";}return "登录失败";}// 查询登录状态,浏览器访问: http://localhost:8101/api/test/user/isLogin@RequestMapping("isLogin")public String isLogin() {return "当前会话是否登录:" + StpUtil.isLogin();}
}

然后可以通过直接访问接口地址来验证。

在这里插入图片描述

Sa-Token 实用功能

按顺序阅读 官方文档 学习即可,重点学习下图中红圈里的内容,其他的作为可选学习项:

Sa-Token 原理

推荐阅读 Sa-Token 文档的 附录部分,尤其是对前后端分离的登录模式不太熟悉的同学。重点阅读以下红圈部分:

Sa-Token 认证流程图,要重点掌握。如果让你自己设计一个权限校验框架,就是按这个流程来:

要理解 Sa-Token 的 Session 模型,区别于 Servlet 的 HttpSession,Sa-Token 维护了自己的 Session,共有 3 种 Session 创建时机:

  • Account-Session: 指的是框架为每个 账号 id 分配的 Session。是分配给账号id的,而不是分配给指定客户端的,也就是说在 PC、APP 上登录的同一账号所得到的 Session 也是同一个,所以两端可以非常轻松的同步数据。
  • Token-Session: 指的是框架为每个 token 分配的 Session·。不同的设备端,哪怕登录了同一账号,只要它们得到的 token 不一致,它们对应的Token-Session就不一致,这就为我们不同端的独立数据读写提供了支持。比如实现“指定客户端超过两小时无操作就自动下线,如果两小时内有操作,就再续期两小时,直到新的两小时无操作”。
  • Custom-Session: 指的是以一个特定的值作为 SessionId,来分配的 Session。不依赖特定的账号id 或者 token,当成一个 Map 去使用即可,比如可以为一个团队的用户指定相同的 SessionId,让一个团队最多 N 个用户同时在线等。


http://www.ppmy.cn/devtools/134933.html

相关文章

卡西莫多的手信2022-2024.11.15

卡西莫多的手信2022-2024.11.15 卡西莫多的手信&#xff0c;上次整理还是9月份&#xff0c;这两个月又增加了一些&#xff0c;增补进集子&#xff1a; 通过网盘分享的文件&#xff1a;卡西莫多的手信2022-2024.11.16-A5.pdf 链接: 百度网盘 请输入提取码 提取码: 9jaw

Python_爬虫1_Requests库入门

目录 Requests库 7个主要方法 Requests库的get()方法 Response对象的属性 爬取网页的通用代码框架 理解requests库的异常 HTTP协议及Requests库方法 HTTP协议 HTTP协议采用URL作为定位网络资源的标识。 HTTP协议对资源的操作 理解PATCH和PUT的区别 HTTP协议与Requse…

SOHO场景开局(小型,多子网):AP+管理型交换机+路由器+光猫

业务需求 1. 实现除光猫外&#xff0c;整网设备通过APP进行开局&#xff0c;开局部署完成后&#xff0c;能够通过APP远程运维。 2. 需要单独划分访客、办公、视频监控3个子网&#xff0c;其中访客子网供顾客无线上网使用&#xff0c;办公子网用于接入无线和有线办公终端&#x…

使用Java绘制图片边框,解决微信小程序map组件中marker与label层级关系问题,label增加外边框后显示不能置与marker上面

今天上线的时候发现系统不同显示好像不一样&#xff0c;苹果手机打开的时候是正常的&#xff0c;但是一旦用安卓手机打开就会出现label不置顶的情况。尝试了很多种办法&#xff0c;也在官方查看了map相关的文档&#xff0c;发现并没有给label设置zIndex的属性&#xff0c;只看到…

ubuntu没有了有线网络如何修复

今天打开ubuntu之后发现有线网络连接没有了&#xff0c;如下图&#xff0c;此时是修复好之后的&#xff0c;“有线”部分存在&#xff0c;出现问题时是不存在的 此时只需要修改NetworkManager.conf配置文件&#xff0c;将managedfalse更改为managedtrue,保存退出就可以了 sudo…

OceansGallerie趣味游戏:带领Web2用户无缝融入Web3世界

引言 随着区块链技术的飞速发展&#xff0c;Web3生态正在逐渐成为数字世界的核心。然而&#xff0c;对于全球10亿Web2用户来说&#xff0c;区块链和Web3的概念依然晦涩难懂。OceansGallerie平台通过设计一个趣味性和奖励性的休闲游戏模块&#xff0c;旨在为这些用户提供一个简…

机器学习周报(transformer学习1)

文章目录 摘要Abstract 1 Transformer1.1 数据部分&#xff0c;输入处理和Embedding1.2 位置编码总结 摘要 本文介绍了Transformer模型的输入结构&#xff0c;包括Embedding层和位置编码的作用与实现。深入了解如何将原始数据转换为模型能够处理的嵌入向量&#xff0c;并探讨了…

树形dp总结

这类题型在 dp 中很常见&#xff0c;于是做一个总结吧&#xff01;&#xff01;&#xff01; 最经典的题&#xff1a;没有上司的舞会 传送门&#xff1a;没有上司的舞会 - 洛谷 状态表示&#xff1a; dp[i][0] 为 以 i 为根的子树中&#xff0c;选择 i 节点的最大欢乐值 d…