filter(ServerWebExchange exchange, WebFilterChain chain) {
+
+ // 写入WebFilterChain对象
+ exchange.getAttributes().put(SaReactorHolder.CHAIN_KEY, chain);
+
+ // ---------- 全局认证处理
+ try {
+ // 写入全局上下文 (同步)
+ SaReactorSyncHolder.setContext(exchange);
+
+ // 执行全局过滤器
+ SaRouter.match(includeList).notMatch(excludeList).check(r -> {
+ beforeAuth.run(null);
+ auth.run(null);
+ });
+
+ } catch (StopMatchException e) {
+
+ } catch (Throwable e) {
+ // 1. 获取异常处理策略结果
+ String result = (e instanceof BackResultException) ? e.getMessage() : String.valueOf(error.run(e));
+
+ // 2. 写入输出流
+ if(exchange.getResponse().getHeaders().getFirst("Content-Type") == null) {
+ exchange.getResponse().getHeaders().set("Content-Type", "text/plain; charset=utf-8");
+ }
+ return exchange.getResponse().writeWith(Mono.just(exchange.getResponse().bufferFactory().wrap(result.getBytes())));
+
+ } finally {
+ // 清除上下文
+ SaReactorSyncHolder.clearContext();
+ }
+
+ // ---------- 执行
+
+ // 写入全局上下文 (同步)
+ SaReactorSyncHolder.setContext(exchange);
+
+ // 执行
+ return chain.filter(exchange).contextWrite(ctx -> {
+ // 写入全局上下文 (异步)
+ ctx = ctx.put(SaReactorHolder.CONTEXT_KEY, exchange);
+ return ctx;
+ }).doFinally(r -> {
+ // 清除上下文
+ SaReactorSyncHolder.clearContext();
+ });
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java
new file mode 100644
index 00000000..da98532e
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaRequestForReactor.java
@@ -0,0 +1,113 @@
+package cn.dev33.satoken.reactor.model;
+
+
+import org.springframework.http.HttpCookie;
+import org.springframework.http.server.reactive.ServerHttpRequest;
+import org.springframework.web.server.ServerWebExchange;
+import org.springframework.web.server.WebFilterChain;
+
+import cn.dev33.satoken.SaManager;
+import cn.dev33.satoken.context.model.SaRequest;
+import cn.dev33.satoken.reactor.context.SaReactorHolder;
+import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
+import cn.dev33.satoken.util.SaFoxUtil;
+
+/**
+ * Request for Reactor
+ * @author kong
+ *
+ */
+public class SaRequestForReactor implements SaRequest {
+
+ /**
+ * 底层Request对象
+ */
+ protected ServerHttpRequest request;
+
+ /**
+ * 实例化
+ * @param request request对象
+ */
+ public SaRequestForReactor(ServerHttpRequest request) {
+ this.request = request;
+ }
+
+ /**
+ * 获取底层源对象
+ */
+ @Override
+ public Object getSource() {
+ return request;
+ }
+
+ /**
+ * 在 [请求体] 里获取一个值
+ */
+ @Override
+ public String getParam(String name) {
+ return request.getQueryParams().getFirst(name);
+ }
+
+ /**
+ * 在 [请求头] 里获取一个值
+ */
+ @Override
+ public String getHeader(String name) {
+ return request.getHeaders().getFirst(name);
+ }
+
+ /**
+ * 在 [Cookie作用域] 里获取一个值
+ */
+ @Override
+ public String getCookieValue(String name) {
+ HttpCookie cookie = request.getCookies().getFirst(name);
+ if(cookie == null) {
+ return null;
+ }
+ return cookie.getValue();
+ }
+
+ /**
+ * 返回当前请求path (不包括上下文名称)
+ */
+ @Override
+ public String getRequestPath() {
+ return request.getURI().getPath();
+ }
+
+ /**
+ * 返回当前请求的url,例:http://xxx.com/test
+ * @return see note
+ */
+ public String getUrl() {
+ String currDomain = SaManager.getConfig().getCurrDomain();
+ if(SaFoxUtil.isEmpty(currDomain) == false) {
+ return currDomain + this.getRequestPath();
+ }
+ return request.getURI().toString();
+ }
+
+ /**
+ * 返回当前请求的类型
+ */
+ @Override
+ public String getMethod() {
+ return request.getMethod().name();
+ }
+
+ /**
+ * 转发请求
+ */
+ @Override
+ public Object forward(String path) {
+ ServerWebExchange exchange = SaReactorSyncHolder.getContext();
+ WebFilterChain chain = exchange.getAttribute(SaReactorHolder.CHAIN_KEY);
+
+ ServerHttpRequest newRequest = request.mutate().path(path).build();
+ ServerWebExchange newExchange = exchange.mutate().request(newRequest).build();
+
+ return chain.filter(newExchange);
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaResponseForReactor.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaResponseForReactor.java
new file mode 100644
index 00000000..3bd6a28b
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaResponseForReactor.java
@@ -0,0 +1,77 @@
+package cn.dev33.satoken.reactor.model;
+
+import java.net.URI;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.server.reactive.ServerHttpResponse;
+
+import cn.dev33.satoken.context.model.SaResponse;
+
+/**
+ * Response for Reactor
+ * @author kong
+ *
+ */
+public class SaResponseForReactor implements SaResponse {
+
+ /**
+ * 底层Response对象
+ */
+ protected ServerHttpResponse response;
+
+ /**
+ * 实例化
+ * @param response response对象
+ */
+ public SaResponseForReactor(ServerHttpResponse response) {
+ this.response = response;
+ }
+
+ /**
+ * 获取底层源对象
+ */
+ @Override
+ public Object getSource() {
+ return response;
+ }
+
+ /**
+ * 设置响应状态码
+ */
+ @Override
+ public SaResponse setStatus(int sc) {
+ response.setStatusCode(HttpStatus.valueOf(sc));
+ return this;
+ }
+
+ /**
+ * 在响应头里写入一个值
+ */
+ @Override
+ public SaResponse setHeader(String name, String value) {
+ response.getHeaders().set(name, value);
+ return this;
+ }
+
+ /**
+ * 在响应头里添加一个值
+ * @param name 名字
+ * @param value 值
+ * @return 对象自身
+ */
+ public SaResponse addHeader(String name, String value) {
+ response.getHeaders().add(name, value);
+ return this;
+ }
+
+ /**
+ * 重定向
+ */
+ @Override
+ public Object redirect(String url) {
+ response.setStatusCode(HttpStatus.FOUND);
+ response.getHeaders().setLocation(URI.create(url));
+ return null;
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaStorageForReactor.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaStorageForReactor.java
new file mode 100644
index 00000000..5cfc080a
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/model/SaStorageForReactor.java
@@ -0,0 +1,61 @@
+package cn.dev33.satoken.reactor.model;
+
+import org.springframework.web.server.ServerWebExchange;
+
+import cn.dev33.satoken.context.model.SaStorage;
+
+/**
+ * Storage for Reactor
+ * @author kong
+ *
+ */
+public class SaStorageForReactor implements SaStorage {
+
+ /**
+ * 底层Request对象
+ */
+ protected ServerWebExchange exchange;
+
+ /**
+ * 实例化
+ * @param exchange exchange对象
+ */
+ public SaStorageForReactor(ServerWebExchange exchange) {
+ this.exchange = exchange;
+ }
+
+ /**
+ * 获取底层源对象
+ */
+ @Override
+ public Object getSource() {
+ return exchange;
+ }
+
+ /**
+ * 在 [Request作用域] 里写入一个值
+ */
+ @Override
+ public SaStorageForReactor set(String key, Object value) {
+ exchange.getAttributes().put(key, value);
+ return this;
+ }
+
+ /**
+ * 在 [Request作用域] 里获取一个值
+ */
+ @Override
+ public Object get(String key) {
+ return exchange.getAttributes().get(key);
+ }
+
+ /**
+ * 在 [Request作用域] 里删除一个值
+ */
+ @Override
+ public SaStorageForReactor delete(String key) {
+ exchange.getAttributes().remove(key);
+ return this;
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/package-info.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/package-info.java
new file mode 100644
index 00000000..bfccfbad
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * sa-token集成Reactor响应式编程的各个组件
+ */
+package cn.dev33.satoken.reactor;
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenContextForSpringReactor.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenContextForSpringReactor.java
new file mode 100644
index 00000000..97912591
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenContextForSpringReactor.java
@@ -0,0 +1,22 @@
+package cn.dev33.satoken.reactor.spring;
+
+import cn.dev33.satoken.context.SaTokenContextForThreadLocal;
+import cn.dev33.satoken.spring.SaPathMatcherHolder;
+
+/**
+ * Sa-Token 上下文处理器 [ Spring Reactor 版本实现 ]
+ *
+ * @author kong
+ *
+ */
+public class SaTokenContextForSpringReactor extends SaTokenContextForThreadLocal {
+
+ /**
+ * 重写路由匹配方法
+ */
+ @Override
+ public boolean matchPath(String pattern, String path) {
+ return SaPathMatcherHolder.getPathMatcher().match(pattern, path);
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenContextRegister.java b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenContextRegister.java
new file mode 100644
index 00000000..3f8ab4f9
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/java/cn/dev33/satoken/reactor/spring/SaTokenContextRegister.java
@@ -0,0 +1,25 @@
+package cn.dev33.satoken.reactor.spring;
+
+import org.springframework.context.annotation.Bean;
+
+import cn.dev33.satoken.context.SaTokenContext;
+
+/**
+ * 注册Sa-Token所需要的Bean
+ * Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
+ * @author kong
+ *
+ */
+public class SaTokenContextRegister {
+
+ /**
+ * 获取容器交互Bean (ThreadLocal版)
+ *
+ * @return 容器交互Bean (ThreadLocal版)
+ */
+ @Bean
+ public SaTokenContext getSaTokenContextForSpringReactor() {
+ return new SaTokenContextForSpringReactor();
+ }
+
+}
diff --git a/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..32577197
--- /dev/null
+++ b/sa-token-starter/sa-token-reactor-spring-boot3-starter/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1 @@
+cn.dev33.satoken.reactor.spring.SaTokenContextRegister
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-servlet/pom.xml b/sa-token-starter/sa-token-servlet/pom.xml
index e3fb2ca7..df2a68c8 100644
--- a/sa-token-starter/sa-token-servlet/pom.xml
+++ b/sa-token-starter/sa-token-servlet/pom.xml
@@ -14,7 +14,7 @@
sa-token-servlet
sa-token-servlet
- sa-token authentication by Sservlet API
+ sa-token authentication by Servlet API
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 7adaabe6..c00126a6 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
@@ -10,8 +10,6 @@ import cn.dev33.satoken.basic.SaBasicUtil;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
import cn.dev33.satoken.dao.SaTokenDao;
-import cn.dev33.satoken.id.SaIdTemplate;
-import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.listener.SaTokenListener;
@@ -28,7 +26,6 @@ import cn.dev33.satoken.temp.SaTempInterface;
* @author noear
* @since 1.4
*/
-@SuppressWarnings("deprecation")
public class XPluginImp implements Plugin {
@Override
@@ -90,11 +87,6 @@ public class XPluginImp implements Plugin {
SaManager.setSaTemp(bean);
});
- // Sa-Token-Id 身份凭证模块 Bean
- context.getBeanAsync(SaIdTemplate.class, bean -> {
- SaIdUtil.saIdTemplate = bean;
- });
-
// Sa-Token Same-Token 模块 Bean
context.getBeanAsync(SaSameTemplate.class, bean -> {
SaManager.setSaSameTemplate(bean);
@@ -120,4 +112,5 @@ public class XPluginImp implements Plugin {
StpUtil.setStpLogic(bean);
});
}
+
}
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/.gitignore b/sa-token-starter/sa-token-spring-boot-autoconfig/.gitignore
new file mode 100644
index 00000000..f56feec7
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.factorypath
+
+.idea/
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/pom.xml b/sa-token-starter/sa-token-spring-boot-autoconfig/pom.xml
new file mode 100644
index 00000000..4ab74948
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/pom.xml
@@ -0,0 +1,57 @@
+
+
+ 4.0.0
+
+
+ cn.dev33
+ sa-token-starter
+ ${revision}
+ ../pom.xml
+
+ jar
+
+ sa-token-spring-boot-autoconfig
+ sa-token-spring-boot-autoconfig
+ sa-token-spring-boot-autoconfig
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+ true
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ true
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+ cn.dev33
+ sa-token-oauth2
+ true
+
+
+
+
+ cn.dev33
+ sa-token-sso
+ true
+
+
+
+
+
+
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/error/SaSpringBootErrorCode.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/error/SaSpringBootErrorCode.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/error/SaSpringBootErrorCode.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/error/SaSpringBootErrorCode.java
diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/package-info.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/package-info.java
new file mode 100644
index 00000000..56ef7301
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/package-info.java
@@ -0,0 +1,4 @@
+/**
+ * sa-token集成SpringBoot的各个组件
+ */
+package cn.dev33.satoken;
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaBeanInject.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaBeanInject.java
similarity index 92%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaBeanInject.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaBeanInject.java
index 6011c2ab..cdfdffc5 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaBeanInject.java
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaBeanInject.java
@@ -13,8 +13,6 @@ import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.context.second.SaTokenSecondContextCreator;
import cn.dev33.satoken.dao.SaTokenDao;
-import cn.dev33.satoken.id.SaIdTemplate;
-import cn.dev33.satoken.id.SaIdUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.listener.SaTokenListener;
@@ -32,7 +30,6 @@ import cn.dev33.satoken.temp.SaTempInterface;
* @author kong
*
*/
-@SuppressWarnings("deprecation")
public class SaBeanInject {
/**
@@ -113,16 +110,6 @@ public class SaBeanInject {
SaManager.setSaTemp(saTemp);
}
- /**
- * 注入 Sa-Id-Token 模块 Bean
- *
- * @param saIdTemplate saIdTemplate对象
- */
- @Autowired(required = false)
- public void setSaIdTemplate(SaIdTemplate saIdTemplate) {
- SaIdUtil.saIdTemplate = saIdTemplate;
- }
-
/**
* 注入 Same-Token 模块 Bean
*
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaBeanRegister.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaBeanRegister.java
similarity index 79%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaBeanRegister.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaBeanRegister.java
index 125d76ff..5b7ffb1e 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaBeanRegister.java
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaBeanRegister.java
@@ -4,7 +4,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import cn.dev33.satoken.config.SaTokenConfig;
-import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.spring.json.SaJsonTemplateForJackson;
@@ -27,16 +26,6 @@ public class SaBeanRegister {
return new SaTokenConfig();
}
- /**
- * 获取上下文Bean (Spring版)
- *
- * @return 容器交互Bean (Spring版)
- */
- @Bean
- public SaTokenContext getSaTokenContext() {
- return new SaTokenContextForSpring();
- }
-
/**
* 获取 json 转换器 Bean (Jackson版)
*
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaPathMatcherHolder.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaPathMatcherHolder.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaPathMatcherHolder.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/SaPathMatcherHolder.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/json/SaJsonTemplateForJackson.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/json/SaJsonTemplateForJackson.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/json/SaJsonTemplateForJackson.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/json/SaJsonTemplateForJackson.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanInject.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/SaOAuth2BeanRegister.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/oauth2/package-info.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/package-info.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/oauth2/package-info.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/oauth2/package-info.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanInject.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/sso/SaSsoBeanRegister.java
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/package-info.java b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/sso/package-info.java
similarity index 100%
rename from sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/sso/package-info.java
rename to sa-token-starter/sa-token-spring-boot-autoconfig/src/main/java/cn/dev33/satoken/spring/sso/package-info.java
diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/resources/META-INF/spring.factories b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/resources/META-INF/spring.factories
new file mode 100644
index 00000000..d092a911
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,7 @@
+org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
+cn.dev33.satoken.spring.SaBeanRegister,\
+cn.dev33.satoken.spring.SaBeanInject,\
+cn.dev33.satoken.spring.sso.SaSsoBeanRegister,\
+cn.dev33.satoken.spring.sso.SaSsoBeanInject,\
+cn.dev33.satoken.spring.oauth2.SaOAuth2BeanRegister,\
+cn.dev33.satoken.spring.oauth2.SaOAuth2BeanInject
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
new file mode 100644
index 00000000..7ea52e5f
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-autoconfig/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports
@@ -0,0 +1,6 @@
+cn.dev33.satoken.spring.SaBeanRegister
+cn.dev33.satoken.spring.SaBeanInject
+cn.dev33.satoken.spring.sso.SaSsoBeanRegister
+cn.dev33.satoken.spring.sso.SaSsoBeanInject
+cn.dev33.satoken.spring.oauth2.SaOAuth2BeanRegister
+cn.dev33.satoken.spring.oauth2.SaOAuth2BeanInject
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot-starter/pom.xml b/sa-token-starter/sa-token-spring-boot-starter/pom.xml
index a05bf634..14939051 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/pom.xml
+++ b/sa-token-starter/sa-token-spring-boot-starter/pom.xml
@@ -17,12 +17,6 @@
springboot integrate sa-token
-
-
- cn.dev33
- sa-token-servlet
-
-
org.springframework.boot
@@ -36,19 +30,18 @@
true
-
+
cn.dev33
- sa-token-oauth2
- true
+ sa-token-servlet
-
+
cn.dev33
- sa-token-sso
- true
+ sa-token-spring-boot-autoconfig
+
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/interceptor/SaAnnotationInterceptor.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/interceptor/SaAnnotationInterceptor.java
deleted file mode 100644
index afa7fa3b..00000000
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/interceptor/SaAnnotationInterceptor.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package cn.dev33.satoken.interceptor;
-
-import java.lang.reflect.Method;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.web.method.HandlerMethod;
-import org.springframework.web.servlet.HandlerInterceptor;
-
-import cn.dev33.satoken.strategy.SaStrategy;
-
-/**
- * Sa-Token 注解式鉴权 - 拦截器
- * [ 当前拦截器写法已过期,可能将在以后的版本删除,推荐升级为 SaInterceptor ]
- *
- * @author kong
- */
-@Deprecated
-public class SaAnnotationInterceptor implements HandlerInterceptor {
-
- /**
- * 构建: 注解式鉴权 - 拦截器
- */
- public SaAnnotationInterceptor() {
- }
-
- /**
- * 每次请求之前触发的方法
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
-
- // 获取处理 Method
- if (handler instanceof HandlerMethod == false) {
- return true;
- }
- Method method = ((HandlerMethod) handler).getMethod();
-
- // 进行验证
- SaStrategy.me.checkMethodAnnotation.accept(method);
-
- // 通过验证
- return true;
- }
-
-}
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/interceptor/SaRouteInterceptor.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/interceptor/SaRouteInterceptor.java
deleted file mode 100644
index 4ce53f11..00000000
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/interceptor/SaRouteInterceptor.java
+++ /dev/null
@@ -1,79 +0,0 @@
-package cn.dev33.satoken.interceptor;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.web.servlet.HandlerInterceptor;
-
-import cn.dev33.satoken.exception.BackResultException;
-import cn.dev33.satoken.exception.StopMatchException;
-import cn.dev33.satoken.router.SaRouteFunction;
-import cn.dev33.satoken.servlet.model.SaRequestForServlet;
-import cn.dev33.satoken.servlet.model.SaResponseForServlet;
-import cn.dev33.satoken.stp.StpUtil;
-
-/**
- * Sa-Token 拦截式鉴权 - 拦截器
- * [ 当前拦截器写法已过期,可能将在以后的版本删除,推荐升级为 SaInterceptor ]
- *
- * @author kong
- */
-@Deprecated
-public class SaRouteInterceptor implements HandlerInterceptor {
-
- /**
- * 每次进入拦截器的[执行函数],默认为登录校验
- */
- public SaRouteFunction function = (req, res, handler) -> StpUtil.checkLogin();
-
- /**
- * 创建一个路由拦截器
- */
- public SaRouteInterceptor() {
- }
-
- /**
- * 创建, 并指定[执行函数]
- * @param function [执行函数]
- */
- public SaRouteInterceptor(SaRouteFunction function) {
- this.function = function;
- }
-
- /**
- * 静态方法快速构建一个
- * @param function 自定义模式下的执行函数
- * @return sa路由拦截器
- */
- public static SaRouteInterceptor newInstance(SaRouteFunction function) {
- return new SaRouteInterceptor(function);
- }
-
-
- // ----------------- 验证方法 -----------------
-
- /**
- * 每次请求之前触发的方法
- */
- @Override
- public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
-
- try {
- function.run(new SaRequestForServlet(request), new SaResponseForServlet(response), handler);
- } catch (StopMatchException e) {
- // 停止匹配,进入Controller
- } catch (BackResultException e) {
- // 停止匹配,向前端输出结果
- if(response.getContentType() == null) {
- response.setContentType("text/plain; charset=utf-8");
- }
- response.getWriter().print(e.getMessage());
- return false;
- }
-
- // 通过验证
- return true;
- }
-
-}
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenContextRegister.java b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenContextRegister.java
new file mode 100644
index 00000000..38fb19b7
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/java/cn/dev33/satoken/spring/SaTokenContextRegister.java
@@ -0,0 +1,25 @@
+package cn.dev33.satoken.spring;
+
+import org.springframework.context.annotation.Bean;
+
+import cn.dev33.satoken.context.SaTokenContext;
+
+/**
+ * 注册Sa-Token所需要的Bean
+ * Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
+ * @author kong
+ *
+ */
+public class SaTokenContextRegister {
+
+ /**
+ * 获取上下文Bean (Spring版)
+ *
+ * @return 容器交互Bean (Spring版)
+ */
+ @Bean
+ public SaTokenContext getSaTokenContextForSpring() {
+ return new SaTokenContextForSpring();
+ }
+
+}
diff --git a/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories b/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories
index d092a911..05745ef3 100644
--- a/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories
+++ b/sa-token-starter/sa-token-spring-boot-starter/src/main/resources/META-INF/spring.factories
@@ -1,7 +1,2 @@
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
-cn.dev33.satoken.spring.SaBeanRegister,\
-cn.dev33.satoken.spring.SaBeanInject,\
-cn.dev33.satoken.spring.sso.SaSsoBeanRegister,\
-cn.dev33.satoken.spring.sso.SaSsoBeanInject,\
-cn.dev33.satoken.spring.oauth2.SaOAuth2BeanRegister,\
-cn.dev33.satoken.spring.oauth2.SaOAuth2BeanInject
\ No newline at end of file
+cn.dev33.satoken.spring.SaTokenContextRegister
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot3-starter/.gitignore b/sa-token-starter/sa-token-spring-boot3-starter/.gitignore
new file mode 100644
index 00000000..f56feec7
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot3-starter/.gitignore
@@ -0,0 +1,12 @@
+target/
+
+node_modules/
+bin/
+.settings/
+unpackage/
+.classpath
+.project
+
+.factorypath
+
+.idea/
\ No newline at end of file
diff --git a/sa-token-starter/sa-token-spring-boot3-starter/pom.xml b/sa-token-starter/sa-token-spring-boot3-starter/pom.xml
new file mode 100644
index 00000000..436e9ad1
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot3-starter/pom.xml
@@ -0,0 +1,77 @@
+
+
+ 4.0.0
+
+
+ cn.dev33
+ sa-token-starter
+ ${revision}
+ ../pom.xml
+
+ jar
+
+ sa-token-spring-boot3-starter
+ sa-token-spring-boot3-starter
+ springboot3 integrate sa-token
+
+
+ 3.0.1
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ true
+
+
+
+
+ cn.dev33
+ sa-token-jakarta-servlet
+
+
+
+
+ cn.dev33
+ sa-token-spring-boot-autoconfig
+
+
+
+
+
+
+
+
+
+ org.springframework.boot
+ spring-boot-starter
+ ${springboot3.version}
+
+
+
+ org.springframework.boot
+ spring-boot-starter-web
+ ${springboot3.version}
+
+
+
+ org.springframework.boot
+ spring-boot-configuration-processor
+ ${springboot3.version}
+
+
+
+
+
+
+
diff --git a/sa-token-starter/sa-token-spring-boot3-starter/src/main/java/cn/dev33/satoken/filter/SaServletFilter.java b/sa-token-starter/sa-token-spring-boot3-starter/src/main/java/cn/dev33/satoken/filter/SaServletFilter.java
new file mode 100644
index 00000000..3c6b40e6
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot3-starter/src/main/java/cn/dev33/satoken/filter/SaServletFilter.java
@@ -0,0 +1,191 @@
+package cn.dev33.satoken.filter;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.springframework.core.annotation.Order;
+
+import cn.dev33.satoken.error.SaSpringBootErrorCode;
+import cn.dev33.satoken.exception.BackResultException;
+import cn.dev33.satoken.exception.SaTokenException;
+import cn.dev33.satoken.exception.StopMatchException;
+import cn.dev33.satoken.router.SaRouter;
+import cn.dev33.satoken.util.SaTokenConsts;
+import jakarta.servlet.Filter;
+import jakarta.servlet.FilterChain;
+import jakarta.servlet.FilterConfig;
+import jakarta.servlet.ServletException;
+import jakarta.servlet.ServletRequest;
+import jakarta.servlet.ServletResponse;
+
+/**
+ * Servlet全局过滤器
+ * @author kong
+ *
+ */
+@Order(SaTokenConsts.ASSEMBLY_ORDER)
+public class SaServletFilter implements Filter {
+
+ // ------------------------ 设置此过滤器 拦截 & 放行 的路由
+
+ /**
+ * 拦截路由
+ */
+ private List includeList = new ArrayList<>();
+
+ /**
+ * 放行路由
+ */
+ private List excludeList = new ArrayList<>();
+
+ /**
+ * 添加 [拦截路由]
+ * @param paths 路由
+ * @return 对象自身
+ */
+ public SaServletFilter addInclude(String... paths) {
+ includeList.addAll(Arrays.asList(paths));
+ return this;
+ }
+
+ /**
+ * 添加 [放行路由]
+ * @param paths 路由
+ * @return 对象自身
+ */
+ public SaServletFilter addExclude(String... paths) {
+ excludeList.addAll(Arrays.asList(paths));
+ return this;
+ }
+
+ /**
+ * 写入 [拦截路由] 集合
+ * @param pathList 路由集合
+ * @return 对象自身
+ */
+ public SaServletFilter setIncludeList(List pathList) {
+ includeList = pathList;
+ return this;
+ }
+
+ /**
+ * 写入 [放行路由] 集合
+ * @param pathList 路由集合
+ * @return 对象自身
+ */
+ public SaServletFilter setExcludeList(List pathList) {
+ excludeList = pathList;
+ return this;
+ }
+
+ /**
+ * 获取 [拦截路由] 集合
+ * @return see note
+ */
+ public List getIncludeList() {
+ return includeList;
+ }
+
+ /**
+ * 获取 [放行路由] 集合
+ * @return see note
+ */
+ public List getExcludeList() {
+ return excludeList;
+ }
+
+
+ // ------------------------ 钩子函数
+
+ /**
+ * 认证函数:每次请求执行
+ */
+ public SaFilterAuthStrategy auth = r -> {};
+
+ /**
+ * 异常处理函数:每次[认证函数]发生异常时执行此函数
+ */
+ public SaFilterErrorStrategy error = e -> {
+ throw new SaTokenException(e).setCode(SaSpringBootErrorCode.CODE_20105);
+ };
+
+ /**
+ * 前置函数:在每次[认证函数]之前执行
+ */
+ public SaFilterAuthStrategy beforeAuth = r -> {};
+
+ /**
+ * 写入[认证函数]: 每次请求执行
+ * @param auth see note
+ * @return 对象自身
+ */
+ public SaServletFilter setAuth(SaFilterAuthStrategy auth) {
+ this.auth = auth;
+ return this;
+ }
+
+ /**
+ * 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数
+ * @param error see note
+ * @return 对象自身
+ */
+ public SaServletFilter setError(SaFilterErrorStrategy error) {
+ this.error = error;
+ return this;
+ }
+
+ /**
+ * 写入[前置函数]:在每次[认证函数]之前执行
+ * @param beforeAuth see note
+ * @return 对象自身
+ */
+ public SaServletFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) {
+ this.beforeAuth = beforeAuth;
+ return this;
+ }
+
+
+ // ------------------------ doFilter
+
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+
+ try {
+ // 执行全局过滤器
+ SaRouter.match(includeList).notMatch(excludeList).check(r -> {
+ beforeAuth.run(null);
+ auth.run(null);
+ });
+
+ } catch (StopMatchException e) {
+
+ } catch (Throwable e) {
+ // 1. 获取异常处理策略结果
+ String result = (e instanceof BackResultException) ? e.getMessage() : String.valueOf(error.run(e));
+
+ // 2. 写入输出流
+ if(response.getContentType() == null) {
+ response.setContentType("text/plain; charset=utf-8");
+ }
+ response.getWriter().print(result);
+ return;
+ }
+
+ // 执行
+ chain.doFilter(request, response);
+ }
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ @Override
+ public void destroy() {
+ }
+
+
+
+}
diff --git a/sa-token-starter/sa-token-spring-boot3-starter/src/main/java/cn/dev33/satoken/interceptor/SaInterceptor.java b/sa-token-starter/sa-token-spring-boot3-starter/src/main/java/cn/dev33/satoken/interceptor/SaInterceptor.java
new file mode 100644
index 00000000..e00450ce
--- /dev/null
+++ b/sa-token-starter/sa-token-spring-boot3-starter/src/main/java/cn/dev33/satoken/interceptor/SaInterceptor.java
@@ -0,0 +1,113 @@
+package cn.dev33.satoken.interceptor;
+
+import java.lang.reflect.Method;
+
+import org.springframework.web.method.HandlerMethod;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import cn.dev33.satoken.annotation.SaIgnore;
+import cn.dev33.satoken.exception.BackResultException;
+import cn.dev33.satoken.exception.StopMatchException;
+import cn.dev33.satoken.fun.SaParamFunction;
+import cn.dev33.satoken.strategy.SaStrategy;
+import jakarta.servlet.http.HttpServletRequest;
+import jakarta.servlet.http.HttpServletResponse;
+
+/**
+ * Sa-Token 综合拦截器,提供注解鉴权和路由拦截鉴权能力
+ *
+ * @author kong
+ * @since: 2022-8-21
+ */
+public class SaInterceptor implements HandlerInterceptor {
+
+ /**
+ * 是否打开注解鉴权
+ */
+ public boolean isAnnotation = true;
+
+ /**
+ * 认证函数:每次请求执行
+ * 参数:路由处理函数指针
+ */
+ public SaParamFunction