注解鉴权增加LoginKey属性,用于多账号模式下的注解鉴权支持

This commit is contained in:
shengzhang
2021-05-04 00:26:44 +08:00
parent 76dd333c9b
commit 479b40b92b
14 changed files with 171 additions and 214 deletions

View File

@@ -11,11 +11,13 @@ import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.context.SaTokenContextDefaultImpl;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.dao.SaTokenDaoDefaultImpl;
import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.listener.SaTokenListenerDefaultImpl;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpInterfaceDefaultImpl;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@@ -34,6 +36,8 @@ public class SaManager {
if(config.getIsV()) {
SaFoxUtil.printSaToken();
}
// 调用一次StpUtil中的方法保证其可以尽早的初始化 StpLogic
StpUtil.getLoginKey();
}
public static SaTokenConfig getConfig() {
if (config == null) {
@@ -153,12 +157,31 @@ public class SaManager {
}
/**
* 根据 LoginKey 获取对应的StpLogic如果不存在则返回null
* 根据 LoginKey 获取对应的StpLogic如果不存在则抛出异常
* @param loginKey 对应的LoginKey
* @return 对应的StpLogic
*/
public static StpLogic getStpLogic(String loginKey) {
return stpLogicMap.get(loginKey);
// 如果key为空则返回框架内置的
if(loginKey == null || loginKey.isEmpty()) {
return StpUtil.stpLogic;
}
// 从SaManager中获取
StpLogic stpLogic = stpLogicMap.get(loginKey);
if(stpLogic == null) {
/*
* 此时有两种情况会造成 StpLogic == null
* 1. LoginKey拼写错误请改正 (建议使用常量)
* 2. 自定义StpUtil尚未初始化静态类中的属性至少一次调用后才会初始化解决方法两种
* (1) 从main方法里调用一次
* (2) 在自定义StpUtil类加上类似 @Component 的注解让容器启动时扫描到自动初始化
*/
throw new SaTokenException("未能获取对应StpLogickey="+ loginKey);
}
// 返回
return stpLogic;
}

View File

@@ -1,5 +1,6 @@
package cn.dev33.satoken.action;
import java.lang.reflect.Method;
import java.util.List;
import cn.dev33.satoken.session.SaSession;
@@ -34,5 +35,11 @@ public interface SaTokenAction {
* @return 是否包含
*/
public boolean hasElement(List<String> list, String element);
/**
* 对一个Method对象进行注解检查注解鉴权内部实现
* @param method Method对象
*/
public void checkMethodAnnotation(Method method);
}

View File

@@ -1,12 +1,16 @@
package cn.dev33.satoken.action;
import java.lang.reflect.Method;
import java.util.List;
import java.util.UUID;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.util.SaTokenConsts;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* 对 SaTokenAction 接口的默认实现
@@ -76,5 +80,53 @@ public class SaTokenActionDefaultImpl implements SaTokenAction {
// 走出for循环说明没有一个元素可以匹配成功
return false;
}
/**
* 对一个Method对象进行注解权限校验注解鉴权逻辑内部实现
*/
@Override
public void checkMethodAnnotation(Method method) {
// 获取这个 Method 所属的 Class
Class<?> clazz = method.getDeclaringClass();
// 从 Class 校验 @SaCheckLogin 注解
if(clazz.isAnnotationPresent(SaCheckLogin.class)) {
SaCheckLogin at = clazz.getAnnotation(SaCheckLogin.class);
SaManager.getStpLogic(at.key()).checkByAnnotation(at);
}
// 从 Class 校验 @SaCheckRole 注解
if(clazz.isAnnotationPresent(SaCheckRole.class)) {
SaCheckRole at = clazz.getAnnotation(SaCheckRole.class);
SaManager.getStpLogic(at.key()).checkByAnnotation(at);
}
// 从 Class 校验 @SaCheckPermission 注解
if(clazz.isAnnotationPresent(SaCheckPermission.class)) {
SaCheckPermission at = clazz.getAnnotation(SaCheckPermission.class);
SaManager.getStpLogic(at.key()).checkByAnnotation(at);
}
// 从 Method 校验 @SaCheckLogin 注解
if(method.isAnnotationPresent(SaCheckLogin.class)) {
SaCheckLogin at = method.getAnnotation(SaCheckLogin.class);
SaManager.getStpLogic(at.key()).checkByAnnotation(at);
}
// 从 Method 校验 @SaCheckRole 注解
if(method.isAnnotationPresent(SaCheckRole.class)) {
SaCheckRole at = method.getAnnotation(SaCheckRole.class);
SaManager.getStpLogic(at.key()).checkByAnnotation(at);
}
// 从 Method 校验 @SaCheckPermission 注解
if(method.isAnnotationPresent(SaCheckPermission.class)) {
SaCheckPermission at = method.getAnnotation(SaCheckPermission.class);
SaManager.getStpLogic(at.key()).checkByAnnotation(at);
}
}
}

View File

@@ -1,7 +1,5 @@
package cn.dev33.satoken.annotation;
import cn.dev33.satoken.stp.StpUtil;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@@ -18,11 +16,9 @@ import java.lang.annotation.Target;
public @interface SaCheckLogin {
/**
* 多账号体系下使用哪个体系检测登录
* 每个StpUtil都有一个stpLogic属性
* 初始化StpLogic时, 指定的LoginKey字符串复制到这里
* @return LoginKey字符串
* 多账号体系下所属的账号体系标识
* @return see note
*/
String key() default "login";
String key() default "";
}

View File

@@ -27,12 +27,10 @@ public @interface SaCheckPermission {
*/
SaMode mode() default SaMode.AND;
/**
* 多账号体系下使用哪个体系检测权限
* 每个StpUtil都有一个stpLogic属性
* 初始化StpLogic时, 指定的LoginKey字符串复制到这里
* @return LoginKey字符串
*/
String key() default "login";
/**
* 多账号体系下所属的账号体系标识
* @return see note
*/
String key() default "";
}

View File

@@ -27,12 +27,10 @@ public @interface SaCheckRole {
*/
SaMode mode() default SaMode.AND;
/**
* 多账号体系下使用哪个体系检测角色
* 每个StpUtil都有一个stpLogic属性
* 初始化StpLogic时, 指定的LoginKey字符串复制到这里
* @return LoginKey字符串
*/
String key() default "login";
/**
* 多账号体系下所属的账号体系标识
* @return see note
*/
String key() default "";
}

View File

@@ -1,5 +1,7 @@
package cn.dev33.satoken.exception;
import cn.dev33.satoken.stp.StpUtil;
/**
* 没有指定权限码,抛出的异常
*
@@ -37,6 +39,10 @@ public class NotPermissionException extends SaTokenException {
return loginKey;
}
public NotPermissionException(String code) {
this(code, StpUtil.stpLogic.loginKey);
}
public NotPermissionException(String code, String loginKey) {
super("无此权限:" + code);
this.code = code;

View File

@@ -1,5 +1,7 @@
package cn.dev33.satoken.exception;
import cn.dev33.satoken.stp.StpUtil;
/**
* 没有指定角色标识,抛出的异常
*
@@ -37,8 +39,11 @@ public class NotRoleException extends SaTokenException {
return loginKey;
}
public NotRoleException(String role) {
this(role, StpUtil.stpLogic.loginKey);
}
public NotRoleException(String role, String loginKey) {
// 这里到底要不要拼接上loginKey呢纠结
super("无此角色:" + role);
this.role = role;
this.loginKey = loginKey;

View File

@@ -1,6 +1,5 @@
package cn.dev33.satoken.stp;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -24,8 +23,8 @@ import cn.dev33.satoken.exception.NotRoleException;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.util.SaTokenConsts;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
/**
* sa-token 权限验证,逻辑实现类
@@ -1219,31 +1218,40 @@ public class StpLogic {
// =================== 其它方法 ===================
/**
* 检查当前登录体系是否拥有给定角色
* @param roleArray 角色字符串数组
* @param saMode SaMode.AND, SaMode.OR
* 根据注解(@SaCheckLogin)鉴权
* @param at 注解对象
*/
public void checkHasRoles(String[] roleArray, SaMode saMode) {
if(saMode == SaMode.AND) {
this.checkRoleAnd(roleArray);
} else {
this.checkRoleOr(roleArray);
}
public void checkByAnnotation(SaCheckLogin at) {
this.checkLogin();
}
/**
* 检查当前登录体系是否拥有给定权限
* @param permissionArray 权限字符串数组
* @param saMode SaMode.AND, SaMode.OR
* 根据注解(@SaCheckRole)鉴权
* @param at 注解对象
*/
public void checkHasPermissions(String[] permissionArray, SaMode saMode) {
if(saMode == SaMode.AND) {
this.checkPermissionAnd(permissionArray);
public void checkByAnnotation(SaCheckRole at) {
String[] roleArray = at.value();
if(at.mode() == SaMode.AND) {
this.checkRoleAnd(roleArray);
} else {
this.checkPermissionOr(permissionArray);
this.checkRoleOr(roleArray);
}
}
/**
* 根据注解(@SaCheckPermission)鉴权
* @param at 注解对象
*/
public void checkByAnnotation(SaCheckPermission at) {
String[] permissionArray = at.value();
if(at.mode() == SaMode.AND) {
this.checkPermissionAnd(permissionArray);
} else {
this.checkPermissionOr(permissionArray);
}
}
// =================== 身份切换 ===================
/**

View File

@@ -10,13 +10,17 @@ import cn.dev33.satoken.session.SaSession;
* @author kong
*/
public class StpUtil {
/**
* 账号体系标识
*/
public static final String KEY = "login";
/**
* 底层的 StpLogic 对象
*/
public static StpLogic stpLogic = new StpLogic("login");
public static StpLogic stpLogic = new StpLogic(KEY);
/**
* 获取当前StpLogin的loginKey
* @return 当前StpLogin的loginKey