mirror of
https://gitee.com/dromara/sa-token.git
synced 2026-05-14 12:52:08 +08:00
新增 SaCheckOr 注解,批量注解鉴权:只要满足其中一个注解即可通过验证
This commit is contained in:
@@ -323,7 +323,7 @@ public class SaManager {
|
||||
synchronized (SaManager.class) {
|
||||
stpLogic = stpLogicMap.get(loginType);
|
||||
if(stpLogic == null) {
|
||||
stpLogic = SaStrategy.me.createStpLogic.apply(loginType);
|
||||
stpLogic = SaStrategy.instance.createStpLogic.apply(loginType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2020-2099 sa-token.cc
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package cn.dev33.satoken.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* 批量注解鉴权:只要满足其中一个注解即可通过验证
|
||||
*
|
||||
* <p> 可标注在方法、类上(效果等同于标注在此类的所有方法上)
|
||||
*
|
||||
* @author kong
|
||||
* @since 1.35.0
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
public @interface SaCheckOr {
|
||||
|
||||
/**
|
||||
* 设定 @SaCheckLogin,参考 {@link SaCheckLogin}
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
SaCheckLogin[] login() default {};
|
||||
|
||||
/**
|
||||
* 设定 @SaCheckPermission,参考 {@link SaCheckPermission}
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
SaCheckPermission[] permission() default {};
|
||||
|
||||
/**
|
||||
* 设定 @SaCheckRole,参考 {@link SaCheckRole}
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
SaCheckRole[] role() default {};
|
||||
|
||||
/**
|
||||
* 设定 @SaCheckSafe,参考 {@link SaCheckSafe}
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
SaCheckSafe[] safe() default {};
|
||||
|
||||
/**
|
||||
* 设定 @SaCheckBasic,参考 {@link SaCheckBasic}
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
SaCheckBasic[] basic() default {};
|
||||
|
||||
/**
|
||||
* 设定 @SaCheckDisable,参考 {@link SaCheckDisable}
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
SaCheckDisable[] disable() default {};
|
||||
|
||||
}
|
||||
@@ -77,7 +77,7 @@ public class SaSessionCustomUtil {
|
||||
public static SaSession getSessionById(String sessionId, boolean isCreate) {
|
||||
SaSession session = SaManager.getSaTokenDao().getSession(splicingSessionKey(sessionId));
|
||||
if (session == null && isCreate) {
|
||||
session = SaStrategy.me.createSession.apply(splicingSessionKey(sessionId));
|
||||
session = SaStrategy.instance.createSession.apply(splicingSessionKey(sessionId));
|
||||
session.setType(SaTokenConsts.SESSION_TYPE__CUSTOM);
|
||||
SaManager.getSaTokenDao().setSession(session, SaManager.getConfig().getTimeout());
|
||||
}
|
||||
|
||||
@@ -123,7 +123,7 @@ public class StpLogic {
|
||||
* @return 生成的tokenValue
|
||||
*/
|
||||
public String createTokenValue(Object loginId, String device, long timeout, Map<String, Object> extraData) {
|
||||
return SaStrategy.me.createToken.apply(loginId, loginType);
|
||||
return SaStrategy.instance.createToken.apply(loginId, loginType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -501,7 +501,7 @@ public class StpLogic {
|
||||
}
|
||||
|
||||
// 4、如果代码走到此处,说明未能成功复用旧 token,需要根据算法新建 token
|
||||
return SaStrategy.me.generateUniqueToken.execute(
|
||||
return SaStrategy.instance.generateUniqueToken.execute(
|
||||
"token",
|
||||
getConfigOfMaxTryTimes(),
|
||||
() -> {
|
||||
@@ -1096,7 +1096,7 @@ public class StpLogic {
|
||||
|
||||
if(session == null && isCreate) {
|
||||
// 创建这个 SaSession
|
||||
session = SaStrategy.me.createSession.apply(sessionId);
|
||||
session = SaStrategy.instance.createSession.apply(sessionId);
|
||||
|
||||
// 追加操作
|
||||
if(appendOperation != null) {
|
||||
@@ -1268,7 +1268,7 @@ public class StpLogic {
|
||||
*/
|
||||
if(isCreate) {
|
||||
// 随机创建一个 Token
|
||||
tokenValue = SaStrategy.me.generateUniqueToken.execute(
|
||||
tokenValue = SaStrategy.instance.generateUniqueToken.execute(
|
||||
"token",
|
||||
getConfigOfMaxTryTimes(),
|
||||
() -> {
|
||||
@@ -2099,8 +2099,8 @@ public class StpLogic {
|
||||
this.checkDisableLevel(loginId, service, at.level());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// ------------------- 账号封禁 -------------------
|
||||
|
||||
/**
|
||||
@@ -2715,7 +2715,7 @@ public class StpLogic {
|
||||
* @return /
|
||||
*/
|
||||
public boolean hasElement(List<String> list, String element) {
|
||||
return SaStrategy.me.hasElement.apply(list, element);
|
||||
return SaStrategy.instance.hasElement.apply(list, element);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,6 +28,7 @@ import cn.dev33.satoken.util.SaTokenConsts;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.function.BiFunction;
|
||||
@@ -58,7 +59,8 @@ public final class SaStrategy {
|
||||
/**
|
||||
* 获取 SaStrategy 对象的单例引用
|
||||
*/
|
||||
public static final SaStrategy me = new SaStrategy();
|
||||
public static final SaStrategy instance = new SaStrategy();
|
||||
|
||||
|
||||
// ----------------------- 所有策略
|
||||
|
||||
@@ -145,10 +147,10 @@ public final class SaStrategy {
|
||||
public Consumer<Method> checkMethodAnnotation = (method) -> {
|
||||
|
||||
// 先校验 Method 所属 Class 上的注解
|
||||
me.checkElementAnnotation.accept(method.getDeclaringClass());
|
||||
instance.checkElementAnnotation.accept(method.getDeclaringClass());
|
||||
|
||||
// 再校验 Method 上的注解
|
||||
me.checkElementAnnotation.accept(method);
|
||||
instance.checkElementAnnotation.accept(method);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -156,41 +158,135 @@ public final class SaStrategy {
|
||||
* <p> 参数 [element元素]
|
||||
*/
|
||||
public Consumer<AnnotatedElement> checkElementAnnotation = (target) -> {
|
||||
|
||||
// 校验 @SaCheckLogin 注解
|
||||
SaCheckLogin checkLogin = (SaCheckLogin) SaStrategy.me.getAnnotation.apply(target, SaCheckLogin.class);
|
||||
SaCheckLogin checkLogin = (SaCheckLogin) SaStrategy.instance.getAnnotation.apply(target, SaCheckLogin.class);
|
||||
if(checkLogin != null) {
|
||||
SaManager.getStpLogic(checkLogin.type(), false).checkByAnnotation(checkLogin);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckRole 注解
|
||||
SaCheckRole checkRole = (SaCheckRole) SaStrategy.me.getAnnotation.apply(target, SaCheckRole.class);
|
||||
SaCheckRole checkRole = (SaCheckRole) SaStrategy.instance.getAnnotation.apply(target, SaCheckRole.class);
|
||||
if(checkRole != null) {
|
||||
SaManager.getStpLogic(checkRole.type(), false).checkByAnnotation(checkRole);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckPermission 注解
|
||||
SaCheckPermission checkPermission = (SaCheckPermission) SaStrategy.me.getAnnotation.apply(target, SaCheckPermission.class);
|
||||
SaCheckPermission checkPermission = (SaCheckPermission) SaStrategy.instance.getAnnotation.apply(target, SaCheckPermission.class);
|
||||
if(checkPermission != null) {
|
||||
SaManager.getStpLogic(checkPermission.type(), false).checkByAnnotation(checkPermission);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckSafe 注解
|
||||
SaCheckSafe checkSafe = (SaCheckSafe) SaStrategy.me.getAnnotation.apply(target, SaCheckSafe.class);
|
||||
SaCheckSafe checkSafe = (SaCheckSafe) SaStrategy.instance.getAnnotation.apply(target, SaCheckSafe.class);
|
||||
if(checkSafe != null) {
|
||||
SaManager.getStpLogic(checkSafe.type(), false).checkByAnnotation(checkSafe);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckDisable 注解
|
||||
SaCheckDisable checkDisable = (SaCheckDisable) SaStrategy.me.getAnnotation.apply(target, SaCheckDisable.class);
|
||||
SaCheckDisable checkDisable = (SaCheckDisable) SaStrategy.instance.getAnnotation.apply(target, SaCheckDisable.class);
|
||||
if(checkDisable != null) {
|
||||
SaManager.getStpLogic(checkDisable.type(), false).checkByAnnotation(checkDisable);
|
||||
}
|
||||
|
||||
// 校验 @SaCheckBasic 注解
|
||||
SaCheckBasic checkBasic = (SaCheckBasic) SaStrategy.me.getAnnotation.apply(target, SaCheckBasic.class);
|
||||
SaCheckBasic checkBasic = (SaCheckBasic) SaStrategy.instance.getAnnotation.apply(target, SaCheckBasic.class);
|
||||
if(checkBasic != null) {
|
||||
SaBasicUtil.check(checkBasic.realm(), checkBasic.account());
|
||||
}
|
||||
|
||||
// 校验 @SaCheckOr 注解
|
||||
SaCheckOr checkOr = (SaCheckOr) SaStrategy.instance.getAnnotation.apply(target, SaCheckOr.class);
|
||||
if(checkOr != null) {
|
||||
SaStrategy.instance.checkOrAnnotation.accept(checkOr);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* 对一个 @SaCheckOr 进行注解校验
|
||||
* <p> 参数 [SaCheckOr 注解的实例]
|
||||
*/
|
||||
public Consumer<SaCheckOr> checkOrAnnotation = (at) -> {
|
||||
|
||||
// 记录校验过程中所有的异常
|
||||
List<SaTokenException> errorList = new ArrayList<>();
|
||||
|
||||
// 逐个开始校验 >>>
|
||||
|
||||
// 1、校验注解:@SaCheckLogin
|
||||
SaCheckLogin[] checkLoginArray = at.login();
|
||||
for (SaCheckLogin item : checkLoginArray) {
|
||||
try {
|
||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 2、校验注解:@SaCheckRole
|
||||
SaCheckRole[] checkRoleArray = at.role();
|
||||
for (SaCheckRole item : checkRoleArray) {
|
||||
try {
|
||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 3、校验注解:@SaCheckPermission
|
||||
SaCheckPermission[] checkPermissionArray = at.permission();
|
||||
for (SaCheckPermission item : checkPermissionArray) {
|
||||
try {
|
||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 4、校验注解:@SaCheckSafe
|
||||
SaCheckSafe[] checkSafeArray = at.safe();
|
||||
for (SaCheckSafe item : checkSafeArray) {
|
||||
try {
|
||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 5、校验注解:@SaCheckDisable
|
||||
SaCheckDisable[] checkDisableArray = at.disable();
|
||||
for (SaCheckDisable item : checkDisableArray) {
|
||||
try {
|
||||
SaManager.getStpLogic(item.type(), false).checkByAnnotation(item);
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 6、校验注解:@SaCheckBasic
|
||||
SaCheckBasic[] checkBasicArray = at.basic();
|
||||
for (SaCheckBasic item : checkBasicArray) {
|
||||
try {
|
||||
SaBasicUtil.check(item.realm(), item.account());
|
||||
return;
|
||||
} catch (SaTokenException e) {
|
||||
errorList.add(e);
|
||||
}
|
||||
}
|
||||
|
||||
// 如果执行到这里,有两种可能:
|
||||
// 可能 1. SaCheckOr 注解上不包含任何注解校验,此时 errorList 里面一个异常都没有,我们直接跳过即可
|
||||
// 可能 2. 所有注解校验都通过不了,此时 errorList 里面会有多个异常,我们随便抛出一个即可
|
||||
if(errorList.size() == 0) {
|
||||
// return;
|
||||
} else {
|
||||
throw errorList.get(0);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -207,8 +303,8 @@ public final class SaStrategy {
|
||||
* <p> 参数 [Method, 注解]
|
||||
*/
|
||||
public BiFunction<Method, Class<? extends Annotation>, Boolean> isAnnotationPresent = (method, annotationClass) -> {
|
||||
return me.getAnnotation.apply(method, annotationClass) != null ||
|
||||
me.getAnnotation.apply(method.getDeclaringClass(), annotationClass) != null;
|
||||
return instance.getAnnotation.apply(method, annotationClass) != null ||
|
||||
instance.getAnnotation.apply(method.getDeclaringClass(), annotationClass) != null;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -308,6 +404,18 @@ public final class SaStrategy {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 对一个 @SaCheckOr 进行注解校验
|
||||
* <p> 参数 [SaCheckOr 注解的实例]
|
||||
*
|
||||
* @param checkOrAnnotation /
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaStrategy setCheckOrAnnotation(Consumer<SaCheckOr> checkOrAnnotation) {
|
||||
this.checkOrAnnotation = checkOrAnnotation;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从元素上获取注解
|
||||
* <p> 参数 [element元素,要获取的注解类型]
|
||||
@@ -355,4 +463,12 @@ public final class SaStrategy {
|
||||
return this;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
/**
|
||||
* 请更换为 instance
|
||||
*/
|
||||
@Deprecated
|
||||
public static final SaStrategy me = instance;
|
||||
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ public interface SaTempInterface {
|
||||
default String createToken(String service, Object value, long timeout) {
|
||||
|
||||
// 生成 token
|
||||
String token = SaStrategy.me.createToken.apply(null, null);
|
||||
String token = SaStrategy.instance.createToken.apply(null, null);
|
||||
|
||||
// 持久化映射关系
|
||||
String key = splicingKeyTempToken(service, token);
|
||||
|
||||
Reference in New Issue
Block a user