引入依赖
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-starter</artifactId>
<version>1.37.0</version>
</dependency>
配置信息
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
代码解析
定义权限类型和用户类型
public enum UserPermission {
//基本权限
BASIC,
//实名认证权限
AUTH,
//无任何权限
NONE;
}
public enum UserRole {
//普通用户
CUSTOMER,
//管理员
ADMIN;
}
登录时将用户信息写入session
//查询用户信息的代码
....
//登录
StpUtil.login(userInfo.getUserId(), new SaLoginModel().setIsLastingCookie(loginParam.getRememberMe())
.setTimeout(DEFAULT_LOGIN_SESSION_TIMEOUT));
//通过StpUtil将用户id存入session
StpUtil.getSession().set(userInfo.getUserId().toString(), userInfo);
通过StpUtil读取session获取用户信息,自定义实现自带StpInterface
接口的getPermissionList
和getRoleList
方法,来获取用户的权限List和角色List。
@Component
public class StpInterfaceImpl implements StpInterface {
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
// 通过StpUtil读取session获取用户id
UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);
if (userInfo.getUserRole() == UserRole.ADMIN || userInfo.getState().equals(UserStateEnum.ACTIVE.name()) || userInfo.getState().equals(UserStateEnum.AUTH.name()) ) {
return List.of(UserPermission.BASIC.name(), UserPermission.AUTH.name());
}
if (userInfo.getState().equals(UserStateEnum.INIT.name())) {
return List.of(UserPermission.BASIC.name());
}
if (userInfo.getState().equals(UserStateEnum.FROZEN.name())) {
return List.of(UserPermission.FROZEN.name());
}
return List.of(UserPermission.NONE.name());
}
@Override
public List<String> getRoleList(Object loginId, String loginType) {
UserInfo userInfo = (UserInfo) StpUtil.getSessionByLoginId(loginId).get((String) loginId);
if (userInfo.getUserRole() == UserRole.ADMIN) {
return List.of(UserRole.ADMIN.name());
}
return List.of(UserRole.CUSTOMER.name());
}
}
通过SaToken鉴权
public SaReactorFilter getSaReactorFilter() {
return new SaReactorFilter()
// 拦截地址
.addInclude("/**")
// 开放地址
.addExclude("/favicon.ico")
// 鉴权方法:每次访问进入
.setAuth(obj -> {
// 登录校验 -- 拦截所有路由,并排除/login 用于开放登录
SaRouter.match("/**").notMatch("/login/**").check(r -> StpUtil.checkLogin());
// 权限认证 -- 不同模块, 校验不同权限
SaRouter.match("/admin/**", r -> StpUtil.checkRole(UserRole.ADMIN.name()));
SaRouter.match("/pay/**", r -> StpUtil.checkPermission(UserPermission.AUTH.name()));
SaRouter.match("/user/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(), UserPermission.AUTH.name()));
SaRouter.match("/order/**", r -> StpUtil.checkPermissionOr(UserPermission.BASIC.name(),UserPermission.AUTH.name()));
})
// 异常处理方法:每次setAuth函数出现异常时进入
.setError(this::getSaResult);
}
权限异常处理
private SaResult getSaResult(Throwable throwable) {
switch (throwable) {
case NotLoginException notLoginException:
log.error("请先登录");
return SaResult.error("请先登录");
case NotRoleException notRoleException:
if (UserRole.ADMIN.name().equals(notRoleException.getRole())) {
log.error("请勿越权使用!");
return SaResult.error("请勿越权使用!");
}
log.error("您无权限进行此操作!");
return SaResult.error("您无权限进行此操作!");
case NotPermissionException notPermissionException:
if (UserPermission.AUTH.name().equals(notPermissionException.getPermission())) {
log.error("请先完成实名认证!");
return SaResult.error("请先完成实名认证!");
}
log.error("您无权限进行此操作!");
return SaResult.error("您无权限进行此操作!");
default:
return SaResult.error(throwable.getMessage());
}
}