废弃 SaTokenAction 接口,新增 SaStrategy 策略类

This commit is contained in:
click33 2021-09-28 23:57:56 +08:00
parent 356e65f749
commit 713e11482c
17 changed files with 234 additions and 88 deletions

View File

@ -27,12 +27,13 @@ import cn.dev33.satoken.util.SaFoxUtil;
* @author kong
*
*/
@SuppressWarnings("deprecation")
public class SaManager {
/**
* 配置文件 Bean
*/
public static SaTokenConfig config;
public volatile static SaTokenConfig config;
public static void setConfig(SaTokenConfig config) {
SaManager.config = config;
if(config.getIsPrint()) {
@ -55,7 +56,7 @@ public class SaManager {
/**
* 持久化 Bean
*/
private static SaTokenDao saTokenDao;
private volatile static SaTokenDao saTokenDao;
public static void setSaTokenDao(SaTokenDao saTokenDao) {
if((SaManager.saTokenDao instanceof SaTokenDaoDefaultImpl)) {
((SaTokenDaoDefaultImpl)SaManager.saTokenDao).endRefreshThread();
@ -76,7 +77,7 @@ public class SaManager {
/**
* 权限认证 Bean
*/
private static StpInterface stpInterface;
private volatile static StpInterface stpInterface;
public static void setStpInterface(StpInterface stpInterface) {
SaManager.stpInterface = stpInterface;
}
@ -94,7 +95,7 @@ public class SaManager {
/**
* 框架行为 Bean
*/
private static SaTokenAction saTokenAction;
private volatile static SaTokenAction saTokenAction;
public static void setSaTokenAction(SaTokenAction saTokenAction) {
SaManager.saTokenAction = saTokenAction;
}
@ -112,7 +113,7 @@ public class SaManager {
/**
* 容器操作 Bean
*/
private static SaTokenContext saTokenContext;
private volatile static SaTokenContext saTokenContext;
public static void setSaTokenContext(SaTokenContext saTokenContext) {
SaManager.saTokenContext = saTokenContext;
}
@ -130,7 +131,7 @@ public class SaManager {
/**
* 侦听器 Bean
*/
private static SaTokenListener saTokenListener;
private volatile static SaTokenListener saTokenListener;
public static void setSaTokenListener(SaTokenListener saTokenListener) {
SaManager.saTokenListener = saTokenListener;
}
@ -148,7 +149,7 @@ public class SaManager {
/**
* 临时令牌验证模块 Bean
*/
private static SaTempInterface saTemp;
private volatile static SaTempInterface saTemp;
public static void setSaTemp(SaTempInterface saTemp) {
SaManager.saTemp = saTemp;
}

View File

@ -1,5 +1,6 @@
package cn.dev33.satoken.action;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.List;
@ -8,9 +9,11 @@ import cn.dev33.satoken.session.SaSession;
/**
* Sa-Token 逻辑代理接口
* <p>此接口将会代理框架内部的一些关键性逻辑方便开发者进行按需重写</p>
* <p> v1.27+ 此接口已废弃目前版本暂时向下兼容请更换为 SaStrategy
* @author kong
*
*/
@Deprecated
public interface SaTokenAction {
/**
@ -42,4 +45,10 @@ public interface SaTokenAction {
*/
public void checkMethodAnnotation(Method method);
/**
* 从指定元素校验注解
* @param target /
*/
public void validateAnnotation(AnnotatedElement target);
}

View File

@ -18,9 +18,11 @@ import cn.dev33.satoken.util.SaTokenConsts;
/**
* Sa-Token 逻辑代理接口 [默认实现类]
* <p> v1.27+ 此接口已废弃目前版本暂时向下兼容请更换为 SaStrategy
* @author kong
*
*/
@Deprecated
public class SaTokenActionDefaultImpl implements SaTokenAction {
/**
@ -110,7 +112,7 @@ public class SaTokenActionDefaultImpl implements SaTokenAction {
* 从指定元素校验注解
* @param target see note
*/
protected void validateAnnotation(AnnotatedElement target) {
public void validateAnnotation(AnnotatedElement target) {
// 校验 @SaCheckLogin 注解
if(target.isAnnotationPresent(SaCheckLogin.class)) {

View File

@ -1,6 +1,7 @@
package cn.dev33.satoken.session;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.strategy.SaStrategy;
/**
* 自定义Session工具类
@ -45,7 +46,7 @@ public class SaSessionCustomUtil {
public static SaSession getSessionById(String sessionId, boolean isCreate) {
SaSession session = SaManager.getSaTokenDao().getSession(splicingSessionKey(sessionId));
if (session == null && isCreate) {
session = SaManager.getSaTokenAction().createSession(splicingSessionKey(sessionId));
session = SaStrategy.me.createSession.apply(splicingSessionKey(sessionId));
SaManager.getSaTokenDao().setSession(session, SaManager.getConfig().getTimeout());
}
return session;

View File

@ -11,6 +11,7 @@ import cn.dev33.satoken.exception.SaTokenException;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.sso.SaSsoConsts.ParamName;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@ -213,7 +214,7 @@ public class SaSsoTemplate {
// 3是否在[允许地址列表]之中
List<String> authUrlList = Arrays.asList(getAllowUrl().replaceAll(" ", "").split(","));
if(SaManager.getSaTokenAction().hasElement(authUrlList, url) == false) {
if(SaStrategy.me.hasElement.apply(authUrlList, url) == false) {
throw new SaTokenException("非法redirect" + url);
}

View File

@ -25,6 +25,7 @@ import cn.dev33.satoken.exception.NotSafeException;
import cn.dev33.satoken.fun.SaFunction;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.session.TokenSign;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
import cn.dev33.satoken.util.SaTokenConsts;
@ -85,7 +86,7 @@ public class StpLogic {
* @return 生成的tokenValue
*/
public String createTokenValue(Object loginId) {
return SaManager.getSaTokenAction().createToken(loginId, loginType);
return SaStrategy.me.createToken.apply(loginId, loginType);
}
/**
@ -539,7 +540,7 @@ public class StpLogic {
public SaSession getSessionBySessionId(String sessionId, boolean isCreate) {
SaSession session = SaManager.getSaTokenDao().getSession(sessionId);
if(session == null && isCreate) {
session = SaManager.getSaTokenAction().createSession(sessionId);
session = SaStrategy.me.createSession.apply(sessionId);
SaManager.getSaTokenDao().setSession(session, getConfig().getTimeout());
}
return session;
@ -842,8 +843,7 @@ public class StpLogic {
*/
public boolean hasRole(Object loginId, String role) {
List<String> roleList = SaManager.getStpInterface().getRoleList(loginId, loginType);
return SaManager.getSaTokenAction().hasElement(roleList, role);
// return !(roleList == null || roleList.contains(role) == false);
return SaStrategy.me.hasElement.apply(roleList, role);
}
/**
@ -873,7 +873,7 @@ public class StpLogic {
Object loginId = getLoginId();
List<String> roleList = SaManager.getStpInterface().getRoleList(loginId, loginType);
for (String role : roleArray) {
if(!SaManager.getSaTokenAction().hasElement(roleList, role)) {
if(!SaStrategy.me.hasElement.apply(roleList, role)) {
throw new NotRoleException(role, this.loginType);
}
}
@ -887,7 +887,7 @@ public class StpLogic {
Object loginId = getLoginId();
List<String> roleList = SaManager.getStpInterface().getRoleList(loginId, loginType);
for (String role : roleArray) {
if(SaManager.getSaTokenAction().hasElement(roleList, role)) {
if(SaStrategy.me.hasElement.apply(roleList, role)) {
// 有的话提前退出
return;
}
@ -908,8 +908,7 @@ public class StpLogic {
*/
public boolean hasPermission(Object loginId, String permission) {
List<String> permissionList = SaManager.getStpInterface().getPermissionList(loginId, loginType);
return SaManager.getSaTokenAction().hasElement(permissionList, permission);
// return !(permissionList == null || permissionList.contains(permission) == false);
return SaStrategy.me.hasElement.apply(permissionList, permission);
}
/**
@ -939,7 +938,7 @@ public class StpLogic {
Object loginId = getLoginId();
List<String> permissionList = SaManager.getStpInterface().getPermissionList(loginId, loginType);
for (String permission : permissionArray) {
if(!SaManager.getSaTokenAction().hasElement(permissionList, permission)) {
if(!SaStrategy.me.hasElement.apply(permissionList, permission)) {
throw new NotPermissionException(permission, this.loginType);
}
}
@ -953,7 +952,7 @@ public class StpLogic {
Object loginId = getLoginId();
List<String> permissionList = SaManager.getStpInterface().getPermissionList(loginId, loginType);
for (String permission : permissionArray) {
if(SaManager.getSaTokenAction().hasElement(permissionList, permission)) {
if(SaStrategy.me.hasElement.apply(permissionList, permission)) {
// 有的话提前退出
return;
}

View File

@ -0,0 +1,143 @@
package cn.dev33.satoken.strategy;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.util.List;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.function.Function;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.session.SaSession;
/**
* Sa-Token 策略对象
* <p>
* 此类统一定义框架内的一些关键性逻辑算法方便开发者进行按需重写
* </p>
*
* @author kong
*
*/
@SuppressWarnings("deprecation")
public final class SaStrategy {
private SaStrategy() {
}
/**
* 获取 SaStrategy 对象的单例引用
*/
public static final SaStrategy me = new SaStrategy();
//
// 所有策略
//
/**
* 创建 Token 的策略
* <p> 参数 [账号id, 账号类型]
*/
public BiFunction<Object, String, String> createToken = (loginId, loginType) -> {
return SaManager.getSaTokenAction().createToken(loginId, loginType);
};
/**
* 创建 Session 的策略
* <p> 参数 [SessionId]
*/
public Function<String, SaSession> createSession = (sessionId) -> {
return SaManager.getSaTokenAction().createSession(sessionId);
};
/**
* 判断集合中是否包含指定元素模糊匹配
* <p> 参数 [集合, 元素]
*/
public BiFunction<List<String>, String, Boolean> hasElement = (list, element) -> {
return SaManager.getSaTokenAction().hasElement(list, element);
};
/**
* 对一个 [Method] 对象进行注解校验 注解鉴权内部实现
* <p> 参数 [Method句柄]
*/
public Consumer<Method> checkMethodAnnotation = (method) -> {
// 先校验 Method 所属 Class 上的注解
me.checkElementAnnotation.accept(method.getDeclaringClass());
// 再校验 Method 上的注解
me.checkElementAnnotation.accept(method);
};
/**
* 对一个 [元素] 对象进行注解校验 注解鉴权内部实现
* <p> 参数 [target元素]
*/
public Consumer<AnnotatedElement> checkElementAnnotation = (element) -> {
SaManager.getSaTokenAction().validateAnnotation(element);
};
//
// 重写策略 set连缀风格
//
/**
* 重写创建 Token 的策略
* <p> 参数 [账号id, 账号类型]
* @param createToken /
* @return 对象自身
*/
public SaStrategy setCreateToken(BiFunction<Object, String, String> createToken) {
this.createToken = createToken;
return this;
}
/**
* 重写创建 Session 的策略
* <p> 参数 [SessionId]
* @param createSession /
* @return 对象自身
*/
public SaStrategy setCreateSession(Function<String, SaSession> createSession) {
this.createSession = createSession;
return this;
}
/**
* 判断集合中是否包含指定元素模糊匹配
* <p> 参数 [集合, 元素]
* @param hasElement /
* @return 对象自身
*/
public SaStrategy setHasElement(BiFunction<List<String>, String, Boolean> hasElement) {
this.hasElement = hasElement;
return this;
}
/**
* 对一个 [Method] 对象进行注解校验 注解鉴权内部实现
* <p> 参数 [Method句柄]
* @param checkMethodAnnotation /
* @return 对象自身
*/
public SaStrategy setCheckMethodAnnotation(Consumer<Method> checkMethodAnnotation) {
this.checkMethodAnnotation = checkMethodAnnotation;
return this;
}
/**
* 对一个 [元素] 对象进行注解校验 注解鉴权内部实现
* <p> 参数 [target元素]
* @param checkElementAnnotation /
* @return 对象自身
*/
public SaStrategy setCheckElementAnnotation(Consumer<AnnotatedElement> checkElementAnnotation) {
this.checkElementAnnotation = checkElementAnnotation;
return this;
}
}

View File

@ -1,6 +1,7 @@
package cn.dev33.satoken.temp;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@ -19,7 +20,7 @@ public interface SaTempInterface {
public default String createToken(Object value, long timeout) {
// 生成 token
String token = SaManager.getSaTokenAction().createToken(null, null);
String token = SaStrategy.me.createToken.apply(null, null);
// 持久化映射关系
String key = splicingKeyTempToken(token);

View File

@ -1,15 +1,26 @@
package com.pj.satoken;
import javax.annotation.PostConstruct;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.pj.util.AjaxJson;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.SaCheckBasic;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaCheckSafe;
import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.filter.SaServletFilter;
import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
import cn.dev33.satoken.strategy.SaStrategy;
/**
@ -21,7 +32,7 @@ import cn.dev33.satoken.interceptor.SaAnnotationInterceptor;
public class SaTokenConfigure implements WebMvcConfigurer {
/**
* 注册sa-token的拦截器打开注解式鉴权功能
* 注册Sa-Token 的拦截器打开注解式鉴权功能
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
@ -30,7 +41,7 @@ public class SaTokenConfigure implements WebMvcConfigurer {
}
/**
* 注册 [sa-token全局过滤器]
* 注册 [Sa-Token 全局过滤器]
*/
@Bean
public SaServletFilter getSaServletFilter() {
@ -69,5 +80,34 @@ public class SaTokenConfigure implements WebMvcConfigurer {
;
}
/**
* 重写 Sa-Token 框架内部算法策略
*/
@PostConstruct
public void rewriteSaStrategy() {
// 重写Sa-Token的注解处理器增加注解合并功能
SaStrategy.me.setCheckElementAnnotation(element -> {
if(AnnotatedElementUtils.isAnnotated(element, SaCheckLogin.class)) {
SaCheckLogin at = AnnotatedElementUtils.getMergedAnnotation(element, SaCheckLogin.class);
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
}
if(AnnotatedElementUtils.isAnnotated(element, SaCheckRole.class)) {
SaCheckRole at = AnnotatedElementUtils.getMergedAnnotation(element, SaCheckRole.class);
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
}
if(AnnotatedElementUtils.isAnnotated(element, SaCheckPermission.class)) {
SaCheckPermission at = AnnotatedElementUtils.getMergedAnnotation(element, SaCheckPermission.class);
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
}
if(AnnotatedElementUtils.isAnnotated(element, SaCheckSafe.class)) {
SaCheckSafe at = AnnotatedElementUtils.getMergedAnnotation(element, SaCheckSafe.class);
SaManager.getStpLogic(null).checkByAnnotation(at);
}
if(AnnotatedElementUtils.isAnnotated(element, SaCheckBasic.class)) {
SaCheckBasic at = AnnotatedElementUtils.getMergedAnnotation(element, SaCheckBasic.class);
SaBasicUtil.check(at.realm(), at.account());
}
});
}
}

View File

@ -1,52 +0,0 @@
package com.pj.satoken.at;
import java.lang.reflect.AnnotatedElement;
import org.springframework.core.annotation.AnnotatedElementUtils;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.action.SaTokenActionDefaultImpl;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.annotation.SaCheckSafe;
/**
* 继承Sa-Token行为Bean默认实现, 重写部分逻辑
*/
//@Component
public class MySaTokenAction extends SaTokenActionDefaultImpl {
/**
* 重写Sa-Token的注解处理器加强注解合并功能
* @param target see note
*/
@Override
protected void validateAnnotation(AnnotatedElement target) {
// 校验 @SaCheckLogin 注解
if(AnnotatedElementUtils.isAnnotated(target, SaCheckLogin.class)) {
SaCheckLogin at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckLogin.class);
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
}
// 校验 @SaCheckRole 注解
if(AnnotatedElementUtils.isAnnotated(target, SaCheckRole.class)) {
SaCheckRole at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckRole.class);
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
}
// 校验 @SaCheckPermission 注解
if(AnnotatedElementUtils.isAnnotated(target, SaCheckPermission.class)) {
SaCheckPermission at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckPermission.class);
SaManager.getStpLogic(at.type()).checkByAnnotation(at);
}
// 校验 @SaCheckSafe 注解
if(AnnotatedElementUtils.isAnnotated(target, SaCheckSafe.class)) {
SaCheckSafe at = AnnotatedElementUtils.getMergedAnnotation(target, SaCheckSafe.class);
SaManager.getStpLogic(null).checkByAnnotation(at);
}
}
}

View File

@ -13,6 +13,7 @@ import cn.dev33.satoken.oauth2.model.CodeModel;
import cn.dev33.satoken.oauth2.model.RefreshTokenModel;
import cn.dev33.satoken.oauth2.model.RequestAuthModel;
import cn.dev33.satoken.oauth2.model.SaClientModel;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaFoxUtil;
/**
@ -358,7 +359,7 @@ public class SaOAuth2Template {
// 3是否在[允许地址列表]之中
List<String> allowList = SaFoxUtil.convertStringToList(checkClientModel(clientId).allowUrl);
if(SaManager.getSaTokenAction().hasElement(allowList, url) == false) {
if(SaStrategy.me.hasElement.apply(allowList, url) == false) {
throw new SaOAuth2Exception("非法redirect_url" + url);
}
}

View File

@ -8,7 +8,7 @@ import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaTokenConsts;
/**
@ -56,7 +56,7 @@ public class SaCheckAspect {
// 注解鉴权
MethodSignature signature = (MethodSignature) joinPoint.getSignature();
SaManager.getSaTokenAction().checkMethodAnnotation(signature.getMethod());
SaStrategy.me.checkMethodAnnotation.accept(signature.getMethod());
try {
// 执行原有逻辑

View File

@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.PathMatcher;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.basic.SaBasicTemplate;
import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.config.SaTokenConfig;
@ -63,7 +62,7 @@ public class SaBeanInject {
* @param saTokenAction SaTokenAction对象
*/
@Autowired(required = false)
public void setSaTokenAction(SaTokenAction saTokenAction) {
public void setSaTokenAction(@SuppressWarnings("deprecation") cn.dev33.satoken.action.SaTokenAction saTokenAction) {
SaManager.setSaTokenAction(saTokenAction);
}

View File

@ -29,6 +29,7 @@ import cn.dev33.satoken.temp.SaTempInterface;
* @author noear
* @since 1.4
*/
@SuppressWarnings("deprecation")
public class XPluginImp implements Plugin {
@Override

View File

@ -1,9 +1,10 @@
package cn.dev33.satoken.solon.integration;
import cn.dev33.satoken.SaManager;
import org.noear.solon.core.aspect.Interceptor;
import org.noear.solon.core.aspect.Invocation;
import cn.dev33.satoken.strategy.SaStrategy;
/**
* @author noear
* @since 1.4
@ -14,8 +15,8 @@ public class SaTokenMethodInterceptor implements Interceptor {
@Override
public Object doIntercept(Invocation inv) throws Throwable {
// 注解鉴权
SaManager.getSaTokenAction().checkMethodAnnotation(inv.method().getMethod());
// 注解鉴权
SaStrategy.me.checkMethodAnnotation.accept(inv.method().getMethod());
// 执行原有逻辑
return inv.invoke();

View File

@ -8,7 +8,7 @@ import javax.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.strategy.SaStrategy;
/**
* 注解式鉴权 - 拦截器
@ -37,7 +37,7 @@ public class SaAnnotationInterceptor implements HandlerInterceptor {
Method method = ((HandlerMethod) handler).getMethod();
// 进行验证
SaManager.getSaTokenAction().checkMethodAnnotation(method);
SaStrategy.me.checkMethodAnnotation.accept(method);
// 通过验证
return true;

View File

@ -5,7 +5,6 @@ import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.PathMatcher;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.action.SaTokenAction;
import cn.dev33.satoken.basic.SaBasicTemplate;
import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.config.SaTokenConfig;
@ -63,7 +62,7 @@ public class SaBeanInject {
* @param saTokenAction SaTokenAction对象
*/
@Autowired(required = false)
public void setSaTokenAction(SaTokenAction saTokenAction) {
public void setSaTokenAction(@SuppressWarnings("deprecation") cn.dev33.satoken.action.SaTokenAction saTokenAction) {
SaManager.setSaTokenAction(saTokenAction);
}