共计 1426 个字符,预计需要花费 4 分钟才能阅读完成。
需要场景
封禁账号是一个比拟常见的业务需要,尤其是在论坛、社区类型的我的项目中,当呈现了违规用户时咱们须要将其账号立刻封禁。
惯例的设计思路是:在设计 用户表
时减少一个状态字段,例如:status
,其值为 1 时代表账号失常,其值为 0 时代表账号已被封禁。
当咱们须要封禁一个账号时,只须要将其账号的 status
值批改为 0 即可,对方再次登录零碎时,咱们便能够检测到 status
值不为 1 禁止登录。
这种模式尽管思路简略,但也有一个不小的问题,那就是: 如果对方始终在线不登记登录呢?
因为咱们只在登录时检测 status
值,这也就代表:如果对方不被动登记账号,他的会话还是会始终存在且无效。
那怎么才能够做到在封禁账号后立刻失效?
你可能会想到应用拦截器,拦挡用户的所有申请检测账号状态:status=0
时禁止拜访,status=1
时再对申请放行
此形式尽管解决了问题,然而如果每次申请都要进行数据库查问的话,数据库示意你如此涤荡我你就没有一点心理压力吗?
那怎么办?上缓存?尽管能够缓解性能压力,但仿佛总感觉没有完满解决问题。
真正的问题点在于:一个失常的零碎只有 0.01% 的用户是须要封禁的,咱们对其它 99.99% 用户的实时检测都是不必要的性能节约。
在如上场景中,咱们真正须要的是一个踢人下线的操作,即:咱们须要在封禁某个用户后,使他的会话立刻掉线,即时他从新登录也会被禁止登录
那么,怎么做到实时踢人下线呢?
笔者应用的是 sa-token 权限认证框架,这个框架封装了踢人下线操作调用十分不便,不必像其它框架一样还须要我本人再封装一层能力做到。
具体代码
- 首先增加
pom.xml
框架
<!-- sa-token 权限认证, 在线文档:http://sa-token.dev33.cn/ -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-starter</artifactId>
<version>1.12.1</version>
</dependency>
复制代码
- 在用户登录时将账号 id 写入会话中
@RestController
@RequestMapping("user")
public class UserController {@RequestMapping("doLogin")
public String doLogin(String username, String password) {
// 此处仅作示例模仿,实在我的项目须要从数据库中查问数据进行比对
if("zhang".equals(username) && "123456".equals(password)) {StpUtil.setLoginId(10001);
return "登录胜利";
}
return "登录失败";
}
}
复制代码
- 将指定 id 的账号
// 使指定 id 账号的会话登记登录,对方再次拜访零碎时会抛出 `NotLoginException` 异样,场景值为 -5
@RequestMapping("kickout")
public String kickout(long userId) {StpUtil.logoutByLoginId(userId);
return "剔出胜利";
}
复制代码
要害代码就在 StpUtil.logoutByLoginId(userId)
这一句,使指定 id 的账号登记登录 (踢人下线)
参考:《2020 最新 Java 根底精讲视频教程和学习路线!》
作者:省长