Sa-Token(四)RBAC 结构实现
目录
一、简介与配置
二、实现登录注销操作
三、权限认证构成与鉴权方法
四、RBAC 结构实现 <— 你在这里 ( •̀ ω •́ )y
Sa-Token(四)RBAC 结构实现
[!NOTE]
博主前言:Spring Security 的学习真是惊掉我下巴,就一个鉴权功能,搞那么多复杂概念,又是过滤器链又是注入的,花了我一个星期左右,实际上还很不好用(未知错误给前端返回 401 是真绷不住)。Sa-Token 作为国产鉴权,性能更强的同时简化开发的程度相比 Spring Security 起码有十倍不止。最近我还注意到对标 Spring 生态的 Solon 框架,也是国产,性能提升3倍多,内存占用减少 50%+,打包还更小,真不知道这些工作为什么老外都做的这么复杂。
了解了 Sa-Token 权限认证的构造,现在我们来动手实现。
基于经典的RBAC
结构实现。
一、准备数据模型
为了实现RBAC
结构,除了第二篇文章的用户(user
),还需准备三个新表,以下为这四个表的结构:
[!NOTE]
我写这篇文档的同时也在编写 Sa-Token 的快速模板,所以用户的结构重构了一下,添加了时间相关字段
user
表
字段名 | 数据类型 | 字符集与排序规则 | 是否允许为空 | 默认值 | 主键 | 唯一键 | 注释 |
---|---|---|---|---|---|---|---|
id | bigint | - | 否 | - | 是 | - | 主键 |
account | varchar(64) | utf8mb4, utf8mb4_zh_0900_as_cs | 否 | - | - | 是 | 账号 |
password | varchar(64) | utf8mb4, utf8mb4_zh_0900_as_cs | 否 | - | - | - | 密码 |
create_time | datetime | - | 否 | - | - | - | 创建时间 |
update_time | datetime | - | 否 | - | - | - | 最近修改时间 |
last_login_time | datetime | - | 否 | - | - | - | 上一次登录时间 |
role
表
字段名 | 数据类型 | 字符集与排序规则 | 是否允许为空 | 默认值 | 主键 | 唯一键 | 注释 |
---|---|---|---|---|---|---|---|
id | bigint | - | 否 | - | 是 | - | 主键 |
name | varchar(64) | utf8mb4, utf8mb4_zh_0900_as_cs | 否 | - | - | 是 | 角色名 |
value | varchar(64) | utf8mb4, utf8mb4_zh_0900_as_cs | 否 | - | - | - | 角色字段 |
create_time | datetime | - | 否 | - | - | - | 创建时间 |
update_time | datetime | - | 否 | - | - | - | 最近修改时间 |
lk_user_role
表
字段名 | 数据类型 | 字符集与排序规则 | 是否允许为空 | 默认值 | 主键 | 外键 | 注释 |
---|---|---|---|---|---|---|---|
id | bigint | - | 否 | - | 是 | - | 主键 |
user_id | bigint | - | 否 | - | - | user(id) | 用户主键 |
role_id | bigint | - | 否 | - | - | role(id) | 角色主键 |
permission
表
字段名 | 数据类型 | 字符集与排序规则 | 是否允许为空 | 默认值 | 主键 | 外键 | 注释 |
---|---|---|---|---|---|---|---|
id | bigint | - | 否 | - | 是 | - | 主键 |
role_id | bigint | - | 否 | - | - | role(id) | 角色主键 |
value | varchar(32) | utf8mb4, utf8mb4_zh_0900_as_cs | 否 | - | - | - | 权限字段 |
建表sql
代码:
[!NOTE]
附带创建的用户密码均为:password
1 | CREATE TABLE `user` ( |
对应的数据结构类:
[!IMPORTANT]
我创建了
BaseEntity
、OnlyCreateTimeEntity
和FullTimeEntity
被数据结构类继承,用于通用地补全id
、create_time
和update_time
这三个字段。
LkUserRole
作为多对多链接键模型类,我对其做了一些特殊处理,读者可以不做,但是对应代码届时需要自行修改补充,详见:代码层多对多结构的通用处理
1 | /** |
权限常量:
1 | /** |
系统默认用户常量:
1 | /** |
二、注册 Sa-Token 拦截器
为了使用注解鉴权和路由鉴权,我们需要在Web
层配置类注册 Sa-Token 拦截器
1 | /** |
三、重写StpInterface
接口
因为每个项目的需求不同,其权限设计也千变万化,因此 [ 获取当前账号权限码集合 ] 这一操作不可能内置到框架中, 所以 Sa-Token 将此操作以接口的方式暴露出来,以方便根据实际业务逻辑进行重写。
按照我们的逻辑模型来说,应将RoleService
继承StpInterface
,并在实现类重写对应方法。
1 | /** |
PermissionService
中的getByRoleId(Long roleId)
实现:
1 | /** |
四、拦截鉴权失败异常并自定义返回
权限错误的异常分别为NotPermissionException
和NotRoleException
,拦截这两个异常即可。
[!TIP]
全局异常配置参考:Spring Boot 全局异常拦截配置
1 | // 均返回 http 403 状态码 |
五、配置权限并测试
准备用户相关接口,均作简略验证,不实现具体逻辑。
验证结果略,读者可自行认证(主要是太多了,偷点懒)。
1 | /** |