diff --git a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/satoken/SaTokenConfigure.java b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/satoken/SaTokenConfigure.java index 2d0ba777..cc483108 100644 --- a/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/satoken/SaTokenConfigure.java +++ b/sa-token-demo/sa-token-demo-solon/src/main/java/com/pj/satoken/SaTokenConfigure.java @@ -22,9 +22,9 @@ public class SaTokenConfigure { /** * 注册 [sa-token全局过滤器] */ - @Bean - public void tokenPathFilter() { - Solon.app().before(new SaTokenPathInterceptor() + @Bean(index = -100) + public SaTokenInterceptor tokenPathFilter() { + return new SaTokenInterceptor() // 指定 [拦截路由] 与 [放行路由] .addInclude("/**").addExclude("/favicon.ico") @@ -55,7 +55,6 @@ public class SaTokenConfigure { // 禁用浏览器内容嗅探 .setHeader("X-Content-Type-Options", "nosniff") ; - }) - ); + }); } } diff --git a/sa-token-dependencies/pom.xml b/sa-token-dependencies/pom.xml index 0039ebf5..bf8b6ab2 100644 --- a/sa-token-dependencies/pom.xml +++ b/sa-token-dependencies/pom.xml @@ -23,7 +23,7 @@ 3.1.0 6.0.0 3.0.9.RELEASE - 1.12.0 + 1.12.2 1.4.4 4.9.17 3.14.4 diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java index c00126a6..9d103e41 100644 --- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/XPluginImp.java @@ -107,8 +107,8 @@ public class XPluginImp implements Plugin { SaManager.setSaSignTemplate(bean); }); - // 自定义 StpLogic 对象(可以有多个) - context.subBeansOfType(StpLogic.class, bean -> { + // 自定义 StpLogic 对象 //容器层面只能有一个;要多个得自己在Util上处理 + context.getBeanAsync(StpLogic.class, bean -> { StpUtil.setStpLogic(bean); }); } diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenFilter.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenFilter.java new file mode 100644 index 00000000..5d7d0f25 --- /dev/null +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenFilter.java @@ -0,0 +1,219 @@ +package cn.dev33.satoken.solon.integration; + +import cn.dev33.satoken.annotation.SaIgnore; +import cn.dev33.satoken.exception.BackResultException; +import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.exception.StopMatchException; +import cn.dev33.satoken.filter.SaFilterAuthStrategy; +import cn.dev33.satoken.filter.SaFilterErrorStrategy; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.strategy.SaStrategy; +import org.noear.solon.Solon; +import org.noear.solon.core.handle.*; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * sa-token 基于路由的过滤式鉴权(增加了注解的处理);使用优先级要低些 + * + * 对静态文件有处理效果 + * + * order: -100 (SaTokenInterceptor 和 SaTokenFilter 二选一;不要同时用) + * + * @author noear + * @since 1.10 + */ +public class SaTokenFilter implements Filter { //之所以改名,为了跟 SaTokenInterceptor 形成一对 + /** + * 是否打开注解鉴权 + */ + public boolean isAnnotation = true; + + // ------------------------ 设置此过滤器 拦截 & 放行 的路由 + + /** + * 拦截路由 + */ + protected List includeList = new ArrayList<>(); + + /** + * 放行路由 + */ + protected List excludeList = new ArrayList<>(); + + /** + * 添加 [拦截路由] + * + * @param paths 路由 + * @return 对象自身 + */ + public SaTokenFilter addInclude(String... paths) { + includeList.addAll(Arrays.asList(paths)); + return this; + } + + /** + * 添加 [放行路由] + * + * @param paths 路由 + * @return 对象自身 + */ + public SaTokenFilter addExclude(String... paths) { + excludeList.addAll(Arrays.asList(paths)); + return this; + } + + /** + * 写入 [拦截路由] 集合 + * + * @param pathList 路由集合 + * @return 对象自身 + */ + public SaTokenFilter setIncludeList(List pathList) { + includeList = pathList; + return this; + } + + /** + * 写入 [放行路由] 集合 + * + * @param pathList 路由集合 + * @return 对象自身 + */ + public SaTokenFilter setExcludeList(List pathList) { + excludeList = pathList; + return this; + } + + /** + * 获取 [拦截路由] 集合 + * + * @return see note + */ + public List getIncludeList() { + return includeList; + } + + /** + * 获取 [放行路由] 集合 + * + * @return see note + */ + public List getExcludeList() { + return excludeList; + } + + + // ------------------------ 钩子函数 + + /** + * 认证函数:每次请求执行 + */ + protected SaFilterAuthStrategy auth = r -> { + }; + + /** + * 异常处理函数:每次[认证函数]发生异常时执行此函数 + */ + protected SaFilterErrorStrategy error = e -> { + if (e instanceof SaTokenException) { + throw (SaTokenException) e; + } else { + throw new SaTokenException(e); + } + }; + + /** + * 前置函数:在每次[认证函数]之前执行 + */ + protected SaFilterAuthStrategy beforeAuth = r -> { + }; + + /** + * 写入[认证函数]: 每次请求执行 + * + * @param auth see note + * @return 对象自身 + */ + public SaTokenFilter setAuth(SaFilterAuthStrategy auth) { + this.auth = auth; + return this; + } + + /** + * 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数 + * + * @param error see note + * @return 对象自身 + */ + public SaTokenFilter setError(SaFilterErrorStrategy error) { + this.error = error; + return this; + } + + /** + * 写入[前置函数]:在每次[认证函数]之前执行 + * + * @param beforeAuth see note + * @return 对象自身 + */ + public SaTokenFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) { + this.beforeAuth = beforeAuth; + return this; + } + + + @Override + public void doFilter(Context ctx, FilterChain chain) throws Throwable { + try { + //查找当前主处理 + Handler mainHandler = Solon.app().router().matchMain(ctx); + + //如果是静态文件,则不处理(静态文件,不在路由中) + if (mainHandler != null) { + Action action = (mainHandler instanceof Action ? (Action) mainHandler : null); + + if (isAnnotation && action != null) { + // 获取此请求对应的 Method 处理函数 + Method method = action.method().getMethod(); + + // 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权 + if (SaStrategy.me.isAnnotationPresent.apply(method, SaIgnore.class)) { + return; + } + + // 注解校验 + SaStrategy.me.checkMethodAnnotation.accept(method); + } + + //路径规则处理 + SaRouter.match(includeList).notMatch(excludeList).check(r -> { + beforeAuth.run(mainHandler); + auth.run(mainHandler); + }); + } + } catch (StopMatchException e) { + + } catch (SaTokenException e) { + // 1. 获取异常处理策略结果 + Object result; + if (e instanceof BackResultException) { + result = e.getMessage(); + } else { + result = error.run(e); + } + + // 2. 写入输出流 + if (result != null) { + ctx.render(result); + } + ctx.setHandled(true); + return; + } + + chain.doFilter(ctx); + } +} diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenInterceptor.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenInterceptor.java new file mode 100644 index 00000000..f16bd2a1 --- /dev/null +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenInterceptor.java @@ -0,0 +1,217 @@ +package cn.dev33.satoken.solon.integration; + +import cn.dev33.satoken.annotation.SaIgnore; +import cn.dev33.satoken.exception.BackResultException; +import cn.dev33.satoken.exception.SaTokenException; +import cn.dev33.satoken.exception.StopMatchException; +import cn.dev33.satoken.filter.SaFilterAuthStrategy; +import cn.dev33.satoken.filter.SaFilterErrorStrategy; +import cn.dev33.satoken.router.SaRouter; +import cn.dev33.satoken.strategy.SaStrategy; +import org.noear.solon.core.handle.*; +import org.noear.solon.core.route.RouterInterceptor; +import org.noear.solon.core.route.RouterInterceptorChain; + +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * sa-token 基于路由的过滤式鉴权(增加了注解的处理);使用优先级要低些 + * + * 对静态文件无处理效果 + * + * order: -100 (SaTokenInterceptor 和 SaTokenFilter 二选一;不要同时用) + * + * @author noear + * @since 1.12 + */ +public class SaTokenInterceptor implements RouterInterceptor { + /** + * 是否打开注解鉴权 + */ + public boolean isAnnotation = true; + + // ------------------------ 设置此过滤器 拦截 & 放行 的路由 + + /** + * 拦截路由 + */ + protected List includeList = new ArrayList<>(); + + /** + * 放行路由 + */ + protected List excludeList = new ArrayList<>(); + + /** + * 添加 [拦截路由] + * + * @param paths 路由 + * @return 对象自身 + */ + public SaTokenInterceptor addInclude(String... paths) { + includeList.addAll(Arrays.asList(paths)); + return this; + } + + /** + * 添加 [放行路由] + * + * @param paths 路由 + * @return 对象自身 + */ + public SaTokenInterceptor addExclude(String... paths) { + excludeList.addAll(Arrays.asList(paths)); + return this; + } + + /** + * 写入 [拦截路由] 集合 + * + * @param pathList 路由集合 + * @return 对象自身 + */ + public SaTokenInterceptor setIncludeList(List pathList) { + includeList = pathList; + return this; + } + + /** + * 写入 [放行路由] 集合 + * + * @param pathList 路由集合 + * @return 对象自身 + */ + public SaTokenInterceptor setExcludeList(List pathList) { + excludeList = pathList; + return this; + } + + /** + * 获取 [拦截路由] 集合 + * + * @return see note + */ + public List getIncludeList() { + return includeList; + } + + /** + * 获取 [放行路由] 集合 + * + * @return see note + */ + public List getExcludeList() { + return excludeList; + } + + + // ------------------------ 钩子函数 + + /** + * 认证函数:每次请求执行 + */ + protected SaFilterAuthStrategy auth = r -> { + }; + + /** + * 异常处理函数:每次[认证函数]发生异常时执行此函数 + */ + protected SaFilterErrorStrategy error = e -> { + if (e instanceof SaTokenException) { + throw (SaTokenException) e; + } else { + throw new SaTokenException(e); + } + }; + + /** + * 前置函数:在每次[认证函数]之前执行 + */ + protected SaFilterAuthStrategy beforeAuth = r -> { + }; + + /** + * 写入[认证函数]: 每次请求执行 + * + * @param auth see note + * @return 对象自身 + */ + public SaTokenInterceptor setAuth(SaFilterAuthStrategy auth) { + this.auth = auth; + return this; + } + + /** + * 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数 + * + * @param error see note + * @return 对象自身 + */ + public SaTokenInterceptor setError(SaFilterErrorStrategy error) { + this.error = error; + return this; + } + + /** + * 写入[前置函数]:在每次[认证函数]之前执行 + * + * @param beforeAuth see note + * @return 对象自身 + */ + public SaTokenInterceptor setBeforeAuth(SaFilterAuthStrategy beforeAuth) { + this.beforeAuth = beforeAuth; + return this; + } + + + @Override + public void doIntercept(Context ctx, Handler mainHandler, RouterInterceptorChain chain) throws Throwable { + try { + //如果是静态文件,则不处理(静态文件,不在路由中) + if (mainHandler != null) { + Action action = (mainHandler instanceof Action ? (Action) mainHandler : null); + + if (isAnnotation && action != null) { + // 获取此请求对应的 Method 处理函数 + Method method = action.method().getMethod(); + + // 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权 + if (SaStrategy.me.isAnnotationPresent.apply(method, SaIgnore.class)) { + return; + } + + // 注解校验 + SaStrategy.me.checkMethodAnnotation.accept(method); + } + + //路径规则处理 + SaRouter.match(includeList).notMatch(excludeList).check(r -> { + beforeAuth.run(mainHandler); + auth.run(mainHandler); + }); + } + } catch (StopMatchException e) { + + } catch (SaTokenException e) { + // 1. 获取异常处理策略结果 + Object result; + if (e instanceof BackResultException) { + result = e.getMessage(); + } else { + result = error.run(e); + } + + // 2. 写入输出流 + if (result != null) { + ctx.render(result); + } + ctx.setHandled(true); + return; + } + + chain.doIntercept(ctx, mainHandler); + } +} diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathFilter.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathFilter.java index 6dba3370..b48bd23a 100644 --- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathFilter.java +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathFilter.java @@ -28,6 +28,7 @@ import cn.dev33.satoken.strategy.SaStrategy; * @author noear * @since 1.10 */ +@Deprecated public class SaTokenPathFilter implements Filter { /** * 是否打开注解鉴权 diff --git a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathInterceptor.java b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathInterceptor.java index 56767702..2e5fb944 100644 --- a/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathInterceptor.java +++ b/sa-token-starter/sa-token-solon-plugin/src/main/java/cn/dev33/satoken/solon/integration/SaTokenPathInterceptor.java @@ -24,6 +24,7 @@ import java.util.List; * @author noear * @since 1.10 */ +@Deprecated public class SaTokenPathInterceptor implements Handler { /** * 是否打开注解鉴权