认证授权
基本说明
登录鉴权功能采用的 Sa-Token 轻量级 Java 权限认证框架, Sa-Token 文档地址
本框架提供了 B、C 端多账号体系认证,B 端代表后台用户,C 端代表前台用户,而且会话信息、授权等是分别独立保存的,互不干涉。
在本框架中 SaToken 的配置如下:
txt
# sa-token配置
sa-token:
# token名称 (同时也是cookie名称)
token-name: access_token
# 关闭输出banner
is-print: false
# SSO-相关配置
sso:
# SSO-Server端 统一认证地址
auth-url: /sso/auth
# 使用Http请求校验ticket
is-http: true
# SSO-Server端 ticket校验地址
check-ticket-url: /sso/checkTicket
# 打开单点注销功能
is-slo: true
# 单点注销地址
slo-url: /sso/signout
# 接口调用秘钥
secretkey: unknown
# SSO-Server端 查询userinfo地址
userinfo-url: /sso/userinfo
# Server 端主机总地址
server-url: http://localhost:3000
# 配置客户端
client: cbb_admin
cookie:
httpOnly: true
登录原理
鉴权原理
SaToken 的鉴权模式原理极其简单易懂,核心逻辑就是判断一个账号是否拥有指定权限,深入到底层数据中,就是每个账号都会拥有一个权限码集合,框架来校验这个集合中是否包含指定的权限码。 使用注解鉴权。
打开 AuthConfigure
这个类,可以清楚的看到,只要告诉系统一个用户的权限码和角色码分别有哪些就可以了:
java
/**
* 权限认证接口实现类,集成权限认证功能
*
* @author tanminglin
* @date 2022/7/7 16:16
**/
@Component
public static class StpInterfaceImpl implements StpInterface {
/**
* 返回一个账号所拥有的权限码集合
*/
@Override
public List<String> getPermissionList(Object loginId, String loginType) {
if (SaClientTypeEnum.B.getValue().equals(loginType)) {
return ListUtil.toList(StpLoginUserUtil.getLoginUser().getPermissions());
}
else {
return ListUtil.toList(StpClientLoginUserUtil.getClientLoginUser().getPermissions());
}
}
/**
* 返回一个账号所拥有的角色标识集合
*/
@Override
public List<String> getRoleList(Object loginId, String loginType) {
if (SaClientTypeEnum.B.getValue().equals(loginType)) {
return ListUtil.toList(StpLoginUserUtil.getLoginUser().getRoles());
}
else {
return ListUtil.toList(StpClientLoginUserUtil.getClientLoginUser().getRoles());
}
}
}
在 AuthServiceImple 中可以看到,角色码和权限码在用户登录的时候就已经查询完毕并缓存:
java
@Override
public SaTokenInfo execLoginB(SaBaseLoginUser saBaseLoginUser, String device) {
// 默认指定为PC,如在小程序跟移动端的情况下,自行指定即可
if (ObjectUtil.isEmpty(device)) {
device = AuthDeviceTypeEnum.PC.getValue();
}
else {
AuthDeviceTypeEnum.validate(device);
}
// 校验状态
if (!saBaseLoginUser.getEnabled()) {
throw new ServiceException(AuthExceptionEnum.ACCOUNT_DISABLED.getValue());
}
// 执行登录
StpUtil.login(saBaseLoginUser.getId(), new SaLoginModel().setDevice(device));
// 获取权限码
saBaseLoginUser.setPermissions(loginUserApi.getPermissionListByUserId(saBaseLoginUser.getId()));
// 获取角色码 并设置了是否是管理员
saBaseLoginUser.setRoles(loginUserApi.getRoleListByUserId(saBaseLoginUser));
// 缓存用户信息,此处使用TokenSession为了指定时间内无操作则自动下线
StpUtil.getTokenSession().set("loginUser", saBaseLoginUser);
// 返回token
return StpUtil.getTokenInfo();
}
PS:因为用户的所有信息都是在登录的时候查询的,因此在给用户授权角色、菜单、数据范围时,需要用户退出重新登录才会生效。
登录监听 打开 AuthListener 可以看到针对登录等一系列的监听方法,如下:
java
/**
* 每次登录时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue 本次登录产生的 token 值
* @param loginModel 登录参数
*/
public void doLogin(String loginType, Object loginId, String tokenValue, SaLoginModel loginModel);
/**
* 每次注销时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public void doLogout(String loginType, Object loginId, String tokenValue);
/**
* 每次被踢下线时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public void doKickout(String loginType, Object loginId, String tokenValue);
/**
* 每次被顶下线时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param tokenValue token值
*/
public void doReplaced(String loginType, Object loginId, String tokenValue);
/**
* 每次被封禁时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param service 指定服务
* @param level 封禁等级
* @param disableTime 封禁时长,单位: 秒
*/
public void doDisable(String loginType, Object loginId, String service, int level, long disableTime);
/**
* 每次被解封时触发
* @param loginType 账号类别
* @param loginId 账号id
* @param service 指定服务
*/
public void doUntieDisable(String loginType, Object loginId, String service);
/**
* 每次打开二级认证时触发
* @param loginType 账号类别
* @param tokenValue token值
* @param service 指定服务
* @param safeTime 认证时间,单位:秒
*/
public void doOpenSafe(String loginType, String tokenValue, String service, long safeTime);
/**
* 每次关闭二级认证时触发
* @param loginType 账号类别
* @param tokenValue token值
* @param service 指定服务
*/
public void doCloseSafe(String loginType, String tokenValue, String service);
/**
* 每次创建Session时触发
* @param id SessionId
*/
public void doCreateSession(String id);
/**
* 每次注销Session时触发
* @param id SessionId
*/
public void doLogoutSession(String id);
/**
* 每次Token续期时触发
*
* @param tokenValue token 值
* @param loginId 账号id
* @param timeout 续期时间
*/
public void doRenewTimeout(String tokenValue, Object loginId, long timeout);
/**
* 全局组件载入
* @param comtName 组件名称
* @param comtObj 组件对象
*/
public default void doRegisterComponent(String comtName, Object comtObj) {}
/**
* StpLogic 对象替换
* @param stpLogic /
*/
public default void doSetStpLogic(StpLogic stpLogic) {}
/**
* 载入全局配置
* @param config /
*/
public default void doSetConfig(SaTokenConfig config) {}