refactor: 重构 springboot 相关集成包,优化依赖关系

This commit is contained in:
click33
2026-02-27 00:25:12 +08:00
parent 9b7efbbcc8
commit 7c95ec51fa
60 changed files with 1720 additions and 858 deletions

View File

@@ -19,6 +19,9 @@
<!-- 所有模块 -->
<modules>
<module>sa-token-dependencies</module>
<module>sa-token-spring-boot2-dependencies</module>
<module>sa-token-spring-boot3-dependencies</module>
<module>sa-token-spring-boot4-dependencies</module>
<module>sa-token-bom</module>
<module>sa-token-core</module>
<module>sa-token-starter</module>
@@ -76,6 +79,10 @@
<dependencyManagement>
<dependencies>
<!--
导入 sa-token-dependencies 所有版本定义,并传导到每个子项目。
需要注意的是:该 import 只会导入 <dependencyManagement> 部分,而不会导入 <dependencies> 部分和 <properties> 部分。
-->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-dependencies</artifactId>

View File

@@ -68,7 +68,12 @@
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<artifactId>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-webmvc-v3v4-common</artifactId>
<version>${revision}</version>
</dependency>
<dependency>

View File

@@ -48,7 +48,7 @@
<!-- Sa-Token整合 Redis (使用jackson序列化方式) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<artifactId>sa-token-redis-template</artifactId>
<version>${sa-token.version}</version>
</dependency>

View File

@@ -38,10 +38,10 @@
<version>${sa-token.version}</version>
</dependency>
<!-- Sa-Token整合 Redis (使用jackson序列化方式) -->
<!-- Sa-Token整合 Redis -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-redis-jackson</artifactId>
<artifactId>sa-token-redis-template</artifactId>
<version>${sa-token.version}</version>
</dependency>
@@ -58,6 +58,7 @@
<optional>true</optional>
</dependency>
</dependencies>

View File

@@ -15,10 +15,10 @@
<revision>1.44.0</revision>
<!-- 统一定义依赖版本号 -->
<springboot.version>2.7.18</springboot.version>
<!-- <springboot.version>2.7.18</springboot.version>-->
<springboot3.version>3.4.3</springboot3.version>
<springboot4.version>4.0.3</springboot4.version>
<spring-web.low.version>5.3.39</spring-web.low.version>
<!-- <spring-web.low.version>5.3.39</spring-web.low.version>-->
<reactor-core.version>3.7.4</reactor-core.version>
<jackson-databind.version>2.13.4.1</jackson-databind.version>
<jackson-datatype-jsr310.version>2.11.2</jackson-datatype-jsr310.version>
@@ -65,13 +65,6 @@
<version>${jakarta-servlet-api.version}</version>
</dependency>
<!-- spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-webmvc (Spring Boot 4) -->
<dependency>
<groupId>org.springframework.boot</groupId>
@@ -79,20 +72,6 @@
<version>${springboot4.version}</version>
</dependency>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-web -->
<!-- <dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.7</version>
</dependency> -->
<!-- reactor-core -->
<dependency>
<groupId>io.projectreactor</groupId>
@@ -100,14 +79,14 @@
<version>${reactor-core.version}</version>
</dependency>
<!-- jackson-databind -->
<!-- jackson2 databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson-databind.version}</version>
</dependency>
<!-- jackson-databind 3.x (tools.jackson) -->
<!-- jackson3 databind (tools.jackson) -->
<dependency>
<groupId>tools.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
@@ -163,26 +142,8 @@
<version>${loveqq.version}</version>
</dependency>
<!-- test -->
<!-- <dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${springboot.version}</version>
</dependency> -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- ****************** sa-token-plugin 相关依赖 ****************** -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- Redisson 相关操作API -->
<dependency>
<groupId>org.redisson</groupId>
@@ -252,26 +213,6 @@
<version>${freemarker.version}</version>
</dependency>
<!-- spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- hutool-jwt -->
<dependency>

View File

@@ -56,10 +56,28 @@
<dependencies>
<!-- spring-boot-configuration -->
<dependency>
<!--<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.5.14</version>
<optional>true</optional>
</dependency>
</dependency>-->
</dependencies>
<dependencyManagement>
<dependencies>
<!-- 默认使用 sa-token springboot2 相关依赖版本定义,子模块也可以引入其它的进行覆盖 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot2-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -32,6 +32,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.5.14</version>
<optional>true</optional>
</dependency>
</dependencies>

View File

@@ -0,0 +1,95 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父仓库 -->
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>pom</packaging>
<artifactId>sa-token-spring-boot2-dependencies</artifactId>
<name>sa-token-spring-boot2-dependencies</name>
<description>Sa-Token SpringBoot2 Dependencies</description>
<properties>
<springboot.version>2.7.18</springboot.version>
<spring-web.low.version>5.3.39</spring-web.low.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-configuration-processor -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring-web.low.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring-web.low.version}</version>
</dependency>
<!-- ****************** sa-token-plugin 相关依赖 ****************** -->
<!-- spring-boot-starter-data-redis -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-thymeleaf -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- spring-boot-starter-actuator -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
<version>${springboot.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父仓库 -->
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>pom</packaging>
<artifactId>sa-token-spring-boot3-dependencies</artifactId>
<name>sa-token-spring-boot3-dependencies</name>
<description>Sa-Token SpringBoot3 Dependencies</description>
<properties>
<springboot3.version>3.0.1</springboot3.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot3.version}</version>
</dependency>
<!-- spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot3.version}</version>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot3.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<!-- 父仓库 -->
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>pom</packaging>
<artifactId>sa-token-spring-boot4-dependencies</artifactId>
<name>sa-token-spring-boot4-dependencies</name>
<description>Sa-Token SpringBoot4 Dependencies</description>
<properties>
<springboot4.version>4.0.3</springboot4.version>
</properties>
<dependencyManagement>
<dependencies>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- spring-boot-starter-webmvc -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot4.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -20,8 +20,9 @@
<modules>
<module>sa-token-servlet</module>
<module>sa-token-jakarta-servlet</module>
<module>sa-token-spring-boot-autoconfig</module>
<module>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</module>
<module>sa-token-spring-boot-starter</module>
<module>sa-token-spring-boot-webmvc-v3v4-common</module>
<module>sa-token-spring-boot3-starter</module>
<module>sa-token-spring-boot4-starter</module>
<module>sa-token-reactor-spring-boot-starter</module>

View File

@@ -51,23 +51,32 @@
<optional>true</optional>
</dependency>
<!-- sa-token-spring-boot-autoconfig -->
<!-- sa-token-spring-boot-webmvc-reactor-v2v3v4-common -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<artifactId>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</artifactId>
</dependency>
<!-- sa-token-jackson: JSON serialization -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.3.39</version>
</dependency>
<!-- sa-token springboot2 相关依赖版本定义 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot2-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

View File

@@ -55,12 +55,18 @@
<optional>true</optional>
</dependency>
<!-- sa-token-spring-boot-autoconfig -->
<!-- sa-token-spring-boot-webmvc-reactor-v2v3v4-common -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<artifactId>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</artifactId>
</dependency>
<!-- sa-token-jackson: JSON serialization -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
@@ -79,13 +85,6 @@
<version>6.2.5</version>
</dependency>
<!-- jackson-databind (optional) -->
<!--<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.1</version>
</dependency>-->
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@@ -30,11 +30,11 @@
<version>5.3.7</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<optional>true</optional>
</dependency>
<!-- <dependency>-->
<!-- <groupId>com.fasterxml.jackson.core</groupId>-->
<!-- <artifactId>jackson-databind</artifactId>-->
<!-- <optional>true</optional>-->
<!-- </dependency>-->
<!-- config (optional) -->
<dependency>
@@ -43,12 +43,6 @@
<optional>true</optional>
</dependency>
<!-- jackson 序列化、redis集成、SSO、OAuth2 等模块要用到,比较重要所以内置集成 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson</artifactId>
</dependency>
<!-- SSO (optional) -->
<dependency>
<groupId>cn.dev33</groupId>

View File

@@ -36,14 +36,33 @@
<artifactId>sa-token-servlet</artifactId>
</dependency>
<!-- sa-token-spring-boot-autoconfig -->
<!-- sa-token-spring-boot-webmvc-reactor-v2v3v4-common -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<artifactId>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</artifactId>
</dependency>
<!-- sa-token-jackson: JSON serialization -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- sa-token springboot2 相关依赖版本定义 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot2-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -0,0 +1,86 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-starter</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>jar</packaging>
<name>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</name>
<artifactId>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</artifactId>
<description>sa-token springboot webmvc/reactor v2/v3/v4 common</description>
<dependencies>
<!-- spring-boot-starter (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<optional>true</optional>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- SSO (optional) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-sso</artifactId>
<optional>true</optional>
</dependency>
<!-- OAuth2.0 (optional) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-oauth2</artifactId>
<optional>true</optional>
</dependency>
<!-- API Key (optional) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-apikey</artifactId>
<optional>true</optional>
</dependency>
<!-- API Sign (optional) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-sign</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- 默认引入 sa-token springboot2 相关依赖版本定义上层可以继续引入其它版本定义来覆盖本层Maven 采用就近原则选择依赖版本 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot2-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -14,6 +14,6 @@
* limitations under the License.
*/
/**
* Sa-Token 集成 SpringBoot4 的各个组件
* Sa-Token 集成 SpringBoot 的各个组件
*/
package cn.dev33.satoken;

View File

@@ -0,0 +1,273 @@
/*
* 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.spring;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.handler.SaAnnotationHandlerInterface;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.context.SaTokenContext;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.fun.strategy.SaCorsHandleFunction;
import cn.dev33.satoken.http.SaHttpTemplate;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicTemplate;
import cn.dev33.satoken.httpauth.basic.SaHttpBasicUtil;
import cn.dev33.satoken.httpauth.digest.SaHttpDigestTemplate;
import cn.dev33.satoken.httpauth.digest.SaHttpDigestUtil;
import cn.dev33.satoken.json.SaJsonTemplate;
import cn.dev33.satoken.listener.SaTokenEventCenter;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.log.SaLog;
import cn.dev33.satoken.plugin.SaTokenPlugin;
import cn.dev33.satoken.plugin.SaTokenPluginHolder;
import cn.dev33.satoken.same.SaSameTemplate;
import cn.dev33.satoken.secure.totp.SaTotpTemplate;
import cn.dev33.satoken.serializer.SaSerializerTemplate;
import cn.dev33.satoken.spring.pathmatch.SaPathMatcherHolder;
import cn.dev33.satoken.stp.StpInterface;
import cn.dev33.satoken.stp.StpLogic;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import cn.dev33.satoken.strategy.SaFirewallStrategy;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.strategy.hooks.SaFirewallCheckHook;
import cn.dev33.satoken.temp.SaTempTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.util.PathMatcher;
import java.util.List;
/**
* 注入 Sa-Token 所需要的 Bean
*
* @author click33
* @since 1.34.0
*/
public class SaBeanInject {
/**
* 组件注入
* <p> 为确保 Log 组件正常打印,必须将 SaLog 和 SaTokenConfig 率先初始化 </p>
*
* @param log log 对象
* @param saTokenConfig 配置对象
*/
public SaBeanInject(
@Autowired(required = false) SaLog log,
@Autowired(required = false) SaTokenConfig saTokenConfig,
@Autowired(required = false) SaTokenPluginHolder pluginHolder
){
if(log != null) {
SaManager.setLog(log);
}
if(saTokenConfig != null) {
SaManager.setConfig(saTokenConfig);
}
// 初始化 Sa-Token SPI 插件
if (pluginHolder == null) {
pluginHolder = SaTokenPluginHolder.instance;
}
pluginHolder.init();
SaTokenPluginHolder.instance = pluginHolder;
}
/**
* 注入持久化Bean
*
* @param saTokenDao SaTokenDao对象
*/
@Autowired(required = false)
public void setSaTokenDao(SaTokenDao saTokenDao) {
SaManager.setSaTokenDao(saTokenDao);
}
/**
* 注入权限认证Bean
*
* @param stpInterface StpInterface对象
*/
@Autowired(required = false)
public void setStpInterface(StpInterface stpInterface) {
SaManager.setStpInterface(stpInterface);
}
/**
* 注入上下文Bean
*
* @param saTokenContext SaTokenContext对象
*/
@Autowired(required = false)
public void setSaTokenContext(SaTokenContext saTokenContext) {
SaManager.setSaTokenContext(saTokenContext);
}
/**
* 注入侦听器Bean
*
* @param listenerList 侦听器集合
*/
@Autowired(required = false)
public void setSaTokenListener(List<SaTokenListener> listenerList) {
SaTokenEventCenter.registerListenerList(listenerList);
}
/**
* 注入自定义注解处理器
*
* @param handlerList 自定义注解处理器集合
*/
@Autowired(required = false)
public void setSaAnnotationHandler(List<SaAnnotationHandlerInterface<?>> handlerList) {
for (SaAnnotationHandlerInterface<?> handler : handlerList) {
SaAnnotationStrategy.instance.registerAnnotationHandler(handler);
}
}
/**
* 注入临时令牌验证模块 Bean
*
* @param saTempTemplate /
*/
@Autowired(required = false)
public void setSaTempTemplate(SaTempTemplate saTempTemplate) {
SaManager.setSaTempTemplate(saTempTemplate);
}
/**
* 注入 Same-Token 模块 Bean
*
* @param saSameTemplate saSameTemplate对象
*/
@Autowired(required = false)
public void setSaIdTemplate(SaSameTemplate saSameTemplate) {
SaManager.setSaSameTemplate(saSameTemplate);
}
/**
* 注入 Sa-Token Http Basic 认证模块
*
* @param saBasicTemplate saBasicTemplate对象
*/
@Autowired(required = false)
public void setSaHttpBasicTemplate(SaHttpBasicTemplate saBasicTemplate) {
SaHttpBasicUtil.saHttpBasicTemplate = saBasicTemplate;
}
/**
* 注入 Sa-Token Http Digest 认证模块
*
* @param saHttpDigestTemplate saHttpDigestTemplate 对象
*/
@Autowired(required = false)
public void setSaHttpDigestTemplate(SaHttpDigestTemplate saHttpDigestTemplate) {
SaHttpDigestUtil.saHttpDigestTemplate = saHttpDigestTemplate;
}
/**
* 注入自定义的 JSON 转换器 Bean
*
* @param saJsonTemplate JSON 转换器
*/
@Autowired(required = false)
public void setSaJsonTemplate(SaJsonTemplate saJsonTemplate) {
SaManager.setSaJsonTemplate(saJsonTemplate);
}
/**
* 注入自定义的 Http 转换器 Bean
*
* @param saHttpTemplate /
*/
@Autowired(required = false)
public void setSaHttpTemplate(SaHttpTemplate saHttpTemplate) {
SaManager.setSaHttpTemplate(saHttpTemplate);
}
/**
* 注入自定义的序列化器 Bean
*
* @param saSerializerTemplate 序列化器
*/
@Autowired(required = false)
public void setSaSerializerTemplate(SaSerializerTemplate saSerializerTemplate) {
SaManager.setSaSerializerTemplate(saSerializerTemplate);
}
/**
* 注入自定义的 TOTP 算法 Bean
*
* @param totpTemplate TOTP 算法类
*/
@Autowired(required = false)
public void setSaTotpTemplate(SaTotpTemplate totpTemplate) {
SaManager.setSaTotpTemplate(totpTemplate);
}
/**
* 注入自定义的 StpLogic
* @param stpLogic /
*/
@Autowired(required = false)
public void setStpLogic(StpLogic stpLogic) {
StpUtil.setStpLogic(stpLogic);
}
/**
* 利用自动注入特性获取Spring框架内部使用的路由匹配器
*
* @param pathMatcher 要设置的 pathMatcher
*/
@Autowired(required = false)
@Qualifier("mvcPathMatcher")
public void setPathMatcher(PathMatcher pathMatcher) {
SaPathMatcherHolder.setPathMatcher(pathMatcher);
}
/**
* 注入自定义防火墙校验 hook 集合
*
* @param hooks /
*/
@Autowired(required = false)
public void setSaFirewallCheckHooks(List<SaFirewallCheckHook> hooks) {
for (SaFirewallCheckHook hook : hooks) {
SaFirewallStrategy.instance.registerHook(hook);
}
}
/**
* 注入CORS 策略处理函数
*
* @param corsHandle /
*/
@Autowired(required = false)
public void setCorsHandle(SaCorsHandleFunction corsHandle) {
SaStrategy.instance.corsHandle = corsHandle;
}
/**
* 注入自定义插件集合
*
* @param plugins /
*/
@Autowired(required = false)
public void setSaTokenPluginList(List<SaTokenPlugin> plugins) {
for (SaTokenPlugin plugin : plugins) {
SaTokenPluginHolder.instance.installPlugin(plugin);
}
}
}

View File

@@ -0,0 +1,51 @@
/*
* 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.spring;
import cn.dev33.satoken.config.SaTokenConfig;
import cn.dev33.satoken.spring.context.path.ApplicationContextPathLoading;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* 注册Sa-Token所需要的Bean
* <p> Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
* @author click33
*
*/
public class SaBeanRegister {
/**
* 获取配置Bean
*
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token")
public SaTokenConfig getSaTokenConfig() {
return new SaTokenConfig();
}
/**
* 应用上下文路径加载器
* @return /
*/
@Bean
public ApplicationContextPathLoading getApplicationContextPathLoading() {
return new ApplicationContextPathLoading();
}
}

View File

@@ -0,0 +1,64 @@
/*
* 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.spring.apikey;
import cn.dev33.satoken.apikey.SaApiKeyManager;
import cn.dev33.satoken.apikey.config.SaApiKeyConfig;
import cn.dev33.satoken.apikey.loader.SaApiKeyDataLoader;
import cn.dev33.satoken.apikey.template.SaApiKeyTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
/**
* 注入 Sa-Token API Key 所需要的 Bean
*
* @author click33
* @since 1.43.0
*/
@ConditionalOnClass(SaApiKeyManager.class)
public class SaApiKeyBeanInject {
/**
* 注入 API Key 配置对象
*
* @param saApiKeyConfig 配置对象
*/
@Autowired(required = false)
public void setSaApiKeyConfig(SaApiKeyConfig saApiKeyConfig) {
SaApiKeyManager.setConfig(saApiKeyConfig);
}
/**
* 注入自定义的 API Key 模版方法 Bean
*
* @param apiKeyTemplate /
*/
@Autowired(required = false)
public void setSaApiKeyTemplate(SaApiKeyTemplate apiKeyTemplate) {
SaApiKeyManager.setSaApiKeyTemplate(apiKeyTemplate);
}
/**
* 注入自定义的 API Key 数据加载器 Bean
*
* @param apiKeyDataLoader /
*/
@Autowired(required = false)
public void setSaApiKeyDataLoader(SaApiKeyDataLoader apiKeyDataLoader) {
SaApiKeyManager.setSaApiKeyDataLoader(apiKeyDataLoader);
}
}

View File

@@ -0,0 +1,43 @@
/*
* 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.spring.apikey;
import cn.dev33.satoken.apikey.SaApiKeyManager;
import cn.dev33.satoken.apikey.config.SaApiKeyConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* 注册 Sa-Token API Key 所需要的 Bean
*
* @author click33
* @since 1.43.0
*/
@ConditionalOnClass(SaApiKeyManager.class)
public class SaApiKeyBeanRegister {
/**
* 获取 API Key 配置对象
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.api-key")
public SaApiKeyConfig getSaApiKeyConfig() {
return new SaApiKeyConfig();
}
}

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
/**
* sa-token-apikey 模块自动化配置(只有引入了 sa-token-apikey 模块后,此包下的代码才会开始工作)
*/
package cn.dev33.satoken.spring.apikey;

View File

@@ -0,0 +1,68 @@
/*
* 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.spring.context.path;
import cn.dev33.satoken.application.ApplicationInfo;
import cn.dev33.satoken.util.SaFoxUtil;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
/**
* 应用上下文路径加载器
*
* @author click33
* @since 1.37.0
*/
public class ApplicationContextPathLoading implements ApplicationRunner {
@Value("${server.servlet.context-path:}")
String contextPath;
@Value("${spring.mvc.servlet.path:}")
String servletPath;
@Override
public void run(ApplicationArguments args) throws Exception {
String routePrefix = "";
if(SaFoxUtil.isNotEmpty(contextPath)) {
if(! contextPath.startsWith("/")){
contextPath = "/" + contextPath;
}
if (contextPath.endsWith("/")) {
contextPath = contextPath.substring(0, contextPath.length() - 1);
}
routePrefix += contextPath;
}
if(SaFoxUtil.isNotEmpty(servletPath)) {
if(! servletPath.startsWith("/")){
servletPath = "/" + servletPath;
}
if (servletPath.endsWith("/")) {
servletPath = servletPath.substring(0, servletPath.length() - 1);
}
routePrefix += servletPath;
}
if(SaFoxUtil.isNotEmpty(routePrefix) && ! routePrefix.equals("/") ){
ApplicationInfo.routePrefix = routePrefix;
}
}
}

View File

@@ -0,0 +1,153 @@
/*
* 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.spring.oauth2;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
import cn.dev33.satoken.oauth2.dao.SaOAuth2Dao;
import cn.dev33.satoken.oauth2.data.convert.SaOAuth2DataConverter;
import cn.dev33.satoken.oauth2.data.generate.SaOAuth2DataGenerate;
import cn.dev33.satoken.oauth2.data.loader.SaOAuth2DataLoader;
import cn.dev33.satoken.oauth2.data.resolver.SaOAuth2DataResolver;
import cn.dev33.satoken.oauth2.granttype.handler.SaOAuth2GrantTypeHandlerInterface;
import cn.dev33.satoken.oauth2.processor.SaOAuth2ServerProcessor;
import cn.dev33.satoken.oauth2.scope.handler.SaOAuth2ScopeHandlerInterface;
import cn.dev33.satoken.oauth2.strategy.SaOAuth2Strategy;
import cn.dev33.satoken.oauth2.template.SaOAuth2Template;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import java.util.List;
// 小提示:如果你在 idea 中运行源码时出现异常java: 程序包cn.dev33.satoken.oauth2不存在。
// 在项目根目录进入 cmd执行 mvn package 即可解决
/**
* 注入 Sa-Token-OAuth2 所需要的组件
*
* @author click33
* @since 1.34.0
*/
@ConditionalOnClass(SaOAuth2Manager.class)
public class SaOAuth2BeanInject {
/**
* 注入 OAuth2 配置对象
*
* @param saOAuth2Config 配置对象
*/
@Autowired(required = false)
public void setSaOAuth2Config(SaOAuth2ServerConfig saOAuth2Config) {
SaOAuth2Manager.setServerConfig(saOAuth2Config);
}
/**
* 注入 OAuth2 模板代码类
*
* @param saOAuth2Template 模板代码类
*/
@Autowired(required = false)
public void setSaOAuth2Template(SaOAuth2Template saOAuth2Template) {
SaOAuth2Manager.setTemplate(saOAuth2Template);
}
/**
* 注入 OAuth2 请求处理器
*
* @param serverProcessor 请求处理器
*/
@Autowired(required = false)
public void setSaOAuth2Template(SaOAuth2ServerProcessor serverProcessor) {
SaOAuth2ServerProcessor.instance = serverProcessor;
}
/**
* 注入 OAuth2 数据加载器
*
* @param dataLoader /
*/
@Autowired(required = false)
public void setSaOAuth2DataLoader(SaOAuth2DataLoader dataLoader) {
SaOAuth2Manager.setDataLoader(dataLoader);
}
/**
* 注入 OAuth2 数据解析器 Bean
*
* @param dataResolver /
*/
@Autowired(required = false)
public void setSaOAuth2DataResolver(SaOAuth2DataResolver dataResolver) {
SaOAuth2Manager.setDataResolver(dataResolver);
}
/**
* 注入 OAuth2 数据格式转换器 Bean
*
* @param dataConverter /
*/
@Autowired(required = false)
public void setSaOAuth2DataConverter(SaOAuth2DataConverter dataConverter) {
SaOAuth2Manager.setDataConverter(dataConverter);
}
/**
* 注入 OAuth2 数据构建器 Bean
*
* @param dataGenerate /
*/
@Autowired(required = false)
public void setSaOAuth2DataGenerate(SaOAuth2DataGenerate dataGenerate) {
SaOAuth2Manager.setDataGenerate(dataGenerate);
}
/**
* 注入 OAuth2 数据持久 Bean
*
* @param dao /
*/
@Autowired(required = false)
public void setSaOAuth2Dao(SaOAuth2Dao dao) {
SaOAuth2Manager.setDao(dao);
}
/**
* 注入自定义 scope 处理器
*
* @param handlerList 自定义 scope 处理器集合
*/
@Autowired(required = false)
public void setSaOAuth2ScopeHandler(List<SaOAuth2ScopeHandlerInterface> handlerList) {
for (SaOAuth2ScopeHandlerInterface handler : handlerList) {
SaOAuth2Strategy.instance.registerScopeHandler(handler);
}
}
/**
* 注入自定义 grant_type 处理器
*
* @param handlerList 自定义 grant_type 处理器集合
*/
@Autowired(required = false)
public void setSaOAuth2GrantTypeHandlerInterface(List<SaOAuth2GrantTypeHandlerInterface> handlerList) {
for (SaOAuth2GrantTypeHandlerInterface handler : handlerList) {
SaOAuth2Strategy.instance.registerGrantTypeHandler(handler);
}
}
}

View File

@@ -0,0 +1,44 @@
/*
* 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.spring.oauth2;
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
import cn.dev33.satoken.oauth2.config.SaOAuth2ServerConfig;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* 注册 Sa-Token-OAuth2 所需要的Bean
*
* @author click33
* @since 1.34.0
*/
@ConditionalOnClass(SaOAuth2Manager.class)
public class SaOAuth2BeanRegister {
/**
* 获取 OAuth2 配置 Bean
*
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.oauth2-server")
public SaOAuth2ServerConfig getSaOAuth2Config() {
return new SaOAuth2ServerConfig();
}
}

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
/**
* Sa-Token-OAuth2 模块自动化配置只有引入了Sa-Token-OAuth2模块后此包下的代码才会开始工作
*/
package cn.dev33.satoken.spring.oauth2;

View File

@@ -0,0 +1,56 @@
/*
* 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.spring.pathmatch;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;
/**
* 路由匹配工具类:持有 PathMatcher 全局引用,方便快捷的调用 PathMatcher 相关方法
*
* @author click33
* @since 1.34.0
*/
public class SaPathMatcherHolder {
private SaPathMatcherHolder() {
}
/**
* 路由匹配器
*/
public static PathMatcher pathMatcher;
/**
* 获取路由匹配器
* @return 路由匹配器
*/
public static PathMatcher getPathMatcher() {
if(pathMatcher == null) {
pathMatcher = new AntPathMatcher();
}
return pathMatcher;
}
/**
* 写入路由匹配器
* @param pathMatcher 路由匹配器
*/
public static void setPathMatcher(PathMatcher pathMatcher) {
SaPathMatcherHolder.pathMatcher = pathMatcher;
}
}

View File

@@ -0,0 +1,53 @@
/*
* 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.spring.pathmatch;
import org.springframework.http.server.PathContainer;
import org.springframework.web.util.pattern.PathPattern;
import org.springframework.web.util.pattern.PathPatternParser;
/**
* 路由匹配工具类:使用 PathPatternParser 模式匹配
*
* @author click33
* @since 1.35.1
*/
public class SaPathPatternParserUtil {
private SaPathPatternParserUtil() {
}
/**
* 判断:指定路由匹配符是否可以匹配成功指定路径
* @param pattern 路由匹配符
* @param path 要匹配的路径
* @return 是否匹配成功
*/
public static boolean match(String pattern, String path) {
PathPattern pathPattern = PathPatternParser.defaultInstance.parse(pattern);
PathContainer pathContainer = PathContainer.parsePath(path);
return pathPattern.matches(pathContainer);
}
/*
表现:
springboot 2.x SpringMVC match("/test/test", "/test/test/") // true
springboot 2.x WebFlux match("/test/test", "/test/test/") // true
springboot 3.x SpringMVC match("/test/test", "/test/test/") // false
springboot 3.x WebFlux match("/test/test", "/test/test/") // false
*/
}

View File

@@ -0,0 +1,71 @@
/*
* 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.spring.pathmatch;
import cn.dev33.satoken.exception.SaTokenException;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 路由匹配工具类
*
* @author click33
* @since 1.35.1
*/
public class SaPatternsRequestConditionHolder {
private SaPatternsRequestConditionHolder() {
}
public static PatternsRequestCondition patternsRequestCondition;
public static Method matcherMethod;
static {
try {
patternsRequestCondition = new PatternsRequestCondition();
matcherMethod = PatternsRequestCondition.class.getDeclaredMethod("getMatchingPattern", String.class, String.class);
matcherMethod.setAccessible(true);
} catch (NoSuchMethodException e) {
throw new SaTokenException("路由匹配器初始化失败", e);
}
}
/**
* 判断:指定路由匹配符是否可以匹配成功指定路径
* @param pattern 路由匹配符
* @param lookupPath 要匹配的路径
* @return 是否匹配成功
*/
public static boolean match(String pattern, String lookupPath) {
try {
return matcherMethod.invoke(patternsRequestCondition, pattern, lookupPath) != null;
} catch (IllegalAccessException | InvocationTargetException e) {
throw new SaTokenException("路由匹配器调用失败", e);
}
}
/*
性能测试:
100万次
new 对象方式耗时3.685s 最慢
反射调方法方式耗时1.311s 中等
原始方式耗时0.445s 最快但有bug
*/
}

View File

@@ -0,0 +1,64 @@
/*
* 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.spring.sign;
import cn.dev33.satoken.sign.SaSignManager;
import cn.dev33.satoken.sign.config.SaSignConfig;
import cn.dev33.satoken.sign.config.SaSignManyConfigWrapper;
import cn.dev33.satoken.sign.template.SaSignTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
/**
* 注入 Sa-Token API 参数签名 所需要的 Bean
*
* @author click33
* @since 1.43.0
*/
@ConditionalOnClass(SaSignManager.class)
public class SaSignBeanInject {
/**
* 注入 API 参数签名配置对象
*
* @param saSignConfig 配置对象
*/
@Autowired(required = false)
public void setSignConfig(SaSignConfig saSignConfig) {
SaSignManager.setConfig(saSignConfig);
}
/**
* 注入 API 参数签名配置对象
*
* @param signManyConfigWrapper 配置对象
*/
@Autowired(required = false)
public void setSignManyConfig(SaSignManyConfigWrapper signManyConfigWrapper) {
SaSignManager.setSignMany(signManyConfigWrapper.getSignMany());
}
/**
* 注入自定义的 参数签名 模版方法 Bean
*
* @param saSignTemplate 参数签名 Bean
*/
@Autowired(required = false)
public void setSaSignTemplate(SaSignTemplate saSignTemplate) {
SaSignManager.setSaSignTemplate(saSignTemplate);
}
}

View File

@@ -0,0 +1,54 @@
/*
* 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.spring.sign;
import cn.dev33.satoken.sign.SaSignManager;
import cn.dev33.satoken.sign.config.SaSignConfig;
import cn.dev33.satoken.sign.config.SaSignManyConfigWrapper;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* 注册 Sa-Token API 参数签名所需要的 Bean
*
* @author click33
* @since 1.43.0
*/
@ConditionalOnClass(SaSignManager.class)
public class SaSignBeanRegister {
/**
* 获取 API 参数签名配置对象
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.sign")
public SaSignConfig getSaSignConfig() {
return new SaSignConfig();
}
/**
* 获取 API 参数签名 Many 配置对象
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token")
public SaSignManyConfigWrapper getSaSignManyConfigWrapper() {
return new SaSignManyConfigWrapper();
}
}

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
/**
* sa-token-sign 模块自动化配置(只有引入了 sa-token-sign 模块后,此包下的代码才会开始工作)
*/
package cn.dev33.satoken.spring.sign;

View File

@@ -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.spring.sso;
import cn.dev33.satoken.sso.SaSsoManager;
import cn.dev33.satoken.sso.config.SaSsoClientConfig;
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
/**
* 注入 Sa-Token SSO 所需要的 Bean
*
* @author click33
* @since 1.34.0
*/
@ConditionalOnClass(SaSsoManager.class)
public class SaSsoBeanInject {
/**
* 注入 Sa-Token SSO Server 端 配置类
*
* @param serverConfig 配置对象
*/
@Autowired(required = false)
public void setSaSsoServerConfig(SaSsoServerConfig serverConfig) {
SaSsoManager.setServerConfig(serverConfig);
}
/**
* 注入 Sa-Token SSO Client 端 配置类
*
* @param clientConfig 配置对象
*/
@Autowired(required = false)
public void setSaSsoClientConfig(SaSsoClientConfig clientConfig) {
SaSsoManager.setClientConfig(clientConfig);
}
/**
* 注入 SSO 模板代码类 (Server 端)
*
* @param ssoServerTemplate /
*/
@Autowired(required = false)
public void setSaSsoServerTemplate(SaSsoServerTemplate ssoServerTemplate) {
SaSsoServerProcessor.instance.ssoServerTemplate = ssoServerTemplate;
}
/**
* 注入 SSO 模板代码类 (Client 端)
*
* @param ssoClientTemplate /
*/
@Autowired(required = false)
public void setSaSsoClientTemplate(SaSsoClientTemplate ssoClientTemplate) {
SaSsoClientProcessor.instance.ssoClientTemplate = ssoClientTemplate;
}
}

View File

@@ -0,0 +1,81 @@
/*
* 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.spring.sso;
import cn.dev33.satoken.sso.SaSsoManager;
import cn.dev33.satoken.sso.config.SaSsoClientConfig;
import cn.dev33.satoken.sso.config.SaSsoServerConfig;
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
import cn.dev33.satoken.sso.processor.SaSsoServerProcessor;
import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
import cn.dev33.satoken.sso.template.SaSsoServerTemplate;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
/**
* 注册 Sa-Token SSO 所需要的 Bean
*
* @author click33
* @since 1.34.0
*/
@ConditionalOnClass(SaSsoManager.class)
public class SaSsoBeanRegister {
/**
* 获取 SSO Server 端 配置对象
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.sso-server")
public SaSsoServerConfig getSaSsoServerConfig() {
return new SaSsoServerConfig();
}
/**
* 获取 SSO Client 端 配置对象
* @return 配置对象
*/
@Bean
@ConfigurationProperties(prefix = "sa-token.sso-client")
public SaSsoClientConfig getSaSsoClientConfig() {
return new SaSsoClientConfig();
}
/**
* 获取 SSO Server 端 SaSsoServerTemplate
*
* @return /
*/
@Bean
@ConditionalOnMissingBean(SaSsoServerTemplate.class)
public SaSsoServerTemplate getSaSsoServerTemplate() {
return SaSsoServerProcessor.instance.ssoServerTemplate;
}
/**
* 获取 SSO Client 端 SaSsoClientTemplate
*
* @return /
*/
@Bean
@ConditionalOnMissingBean(SaSsoClientTemplate.class)
public SaSsoClientTemplate getSaSsoClientTemplate() {
return SaSsoClientProcessor.instance.ssoClientTemplate;
}
}

View File

@@ -0,0 +1,19 @@
/*
* 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.
*/
/**
* Sa-Token-SSO 模块自动化配置(只有引入了 sa-token-sso 模块后,此包下的代码才会开始工作)
*/
package cn.dev33.satoken.spring.sso;

View File

@@ -0,0 +1,11 @@
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,\
cn.dev33.satoken.spring.apikey.SaApiKeyBeanRegister,\
cn.dev33.satoken.spring.apikey.SaApiKeyBeanInject,\
cn.dev33.satoken.spring.sign.SaSignBeanRegister,\
cn.dev33.satoken.spring.sign.SaSignBeanInject

View File

@@ -0,0 +1,10 @@
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
cn.dev33.satoken.spring.apikey.SaApiKeyBeanRegister
cn.dev33.satoken.spring.apikey.SaApiKeyBeanInject
cn.dev33.satoken.spring.sign.SaSignBeanRegister
cn.dev33.satoken.spring.sign.SaSignBeanInject

View File

@@ -0,0 +1,63 @@
<?xml version='1.0' encoding='utf-8'?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-starter</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<packaging>jar</packaging>
<name>sa-token-spring-boot-webmvc-v3v4-common</name>
<artifactId>sa-token-spring-boot-webmvc-v3v4-common</artifactId>
<description>sa-token springboot webmvc v3v4 common</description>
<dependencies>
<!-- spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<optional>true</optional>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- sa-token-jakarta-servlet -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jakarta-servlet</artifactId>
</dependency>
<!-- sa-token-spring-boot-webmvc-reactor-v2v3v4-common -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-webmvc-reactor-v2v3v4-common</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<!-- 默认引入 sa-token springboot3 相关依赖版本定义上层可以继续引入其它版本定义来覆盖本层Maven 采用就近原则选择依赖版本 -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -16,62 +16,36 @@
<artifactId>sa-token-spring-boot3-starter</artifactId>
<description>springboot3 integrate sa-token</description>
<properties>
<springboot3.version>3.0.1</springboot3.version>
</properties>
<dependencies>
<!-- spring-boot-starter-web -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- sa-token-jakarta-servlet -->
<!-- sa-token-spring-boot-webmvc-v3v4-common -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jakarta-servlet</artifactId>
<artifactId>sa-token-spring-boot-webmvc-v3v4-common</artifactId>
</dependency>
<!-- sa-token-spring-boot-autoconfig -->
<!-- sa-token-jackson: JSON serialization for Spring Boot 3 (Jackson 2.x) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<artifactId>sa-token-jackson</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependencyManagement>
<dependencies>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot3.version}</version>
</dependency>
<!-- spring-boot-starter-web -->
<!-- sa-token springboot3 相关依赖版本定义 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot3.version}</version>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot3.version}</version>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot3-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
</dependencies>
</dependencyManagement>
</project>

View File

@@ -16,40 +16,12 @@
<artifactId>sa-token-spring-boot4-starter</artifactId>
<description>springboot4 integrate sa-token</description>
<properties>
<springboot4.version>4.0.3</springboot4.version>
</properties>
<dependencies>
<!-- spring-boot-starter-webmvc (Spring Boot 4 recommended, replaces deprecated starter-web) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<!-- sa-token-jakarta-servlet -->
<!-- sa-token-spring-boot-webmvc-v3v4-common -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jakarta-servlet</artifactId>
</dependency>
<!-- sa-token-spring-boot-autoconfig (exclude sa-token-jackson, use sa-token-jackson3 for Spring Boot 4) -->
<dependency>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
<exclusions>
<exclusion>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-jackson</artifactId>
</exclusion>
</exclusions>
<artifactId>sa-token-spring-boot-webmvc-v3v4-common</artifactId>
</dependency>
<!-- sa-token-jackson3: JSON serialization for Spring Boot 4 (Jackson 3) -->
@@ -63,39 +35,16 @@
<dependencyManagement>
<dependencies>
<!-- spring-boot-starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- spring-boot-starter-webmvc -->
<!-- sa-token springboot4 相关依赖版本定义 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
<version>${springboot4.version}</version>
</dependency>
<!-- config (optional) -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>${springboot4.version}</version>
<groupId>cn.dev33</groupId>
<artifactId>sa-token-spring-boot4-dependencies</artifactId>
<version>${revision}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>17</source>
<target>17</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,73 +0,0 @@
/*
* 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.filter;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.FirewallCheckException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
import cn.dev33.satoken.servlet.util.SaJakartaServletOperateUtil;
import cn.dev33.satoken.strategy.SaFirewallStrategy;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import java.io.IOException;
/**
* 防火墙校验过滤器 (基于 Jakarta-Servlet)
*
* @author click33
* @since 1.37.0
*/
@Order(SaTokenConsts.FIREWALL_CHECK_FILTER_ORDER)
public class SaFirewallCheckFilterForJakartaServlet implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
SaRequestForServlet saRequest = new SaRequestForServlet(req);
SaResponseForServlet saResponse = new SaResponseForServlet(res);
try {
SaFirewallStrategy.instance.check.execute(saRequest, saResponse, null);
}
catch (StopMatchException ignored) {}
catch (BackResultException e) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
return;
}
catch (FirewallCheckException e) {
if(SaFirewallStrategy.instance.checkFailHandle == null) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
} else {
SaFirewallStrategy.instance.checkFailHandle.run(e, saRequest, saResponse, null);
}
return;
}
// 更多异常则不处理,交由 Web 框架处理
// 向内执行
chain.doFilter(request, response);
}
}

View File

@@ -1,146 +0,0 @@
/*
* 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.filter;
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.servlet.util.SaJakartaServletOperateUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import org.springframework.core.annotation.Order;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* 全局鉴权过滤器 (基于 Jakarta-Servlet)
* <p>
* 默认优先级为 -100尽量保证在其它过滤器之前执行
* </p>
*
* @author click33
* @since 1.34.0
*/
@Order(SaTokenConsts.ASSEMBLY_ORDER)
public class SaServletFilter implements SaFilter, Filter {
// ------------------------ 设置此过滤器 拦截 & 放行 的路由
/**
* 拦截路由
*/
public List<String> includeList = new ArrayList<>();
/**
* 放行路由
*/
public List<String> excludeList = new ArrayList<>();
@Override
public SaServletFilter addInclude(String... paths) {
includeList.addAll(Arrays.asList(paths));
return this;
}
@Override
public SaServletFilter addExclude(String... paths) {
excludeList.addAll(Arrays.asList(paths));
return this;
}
@Override
public SaServletFilter setIncludeList(List<String> pathList) {
includeList = pathList;
return this;
}
@Override
public SaServletFilter setExcludeList(List<String> pathList) {
excludeList = pathList;
return this;
}
// ------------------------ 钩子函数
/**
* 认证函数:每次请求执行
*/
public SaFilterAuthStrategy auth = r -> {};
/**
* 异常处理函数:每次[认证函数]发生异常时执行此函数
*/
public SaFilterErrorStrategy error = e -> {
throw new SaTokenException(e);
};
/**
* 前置函数:在每次[认证函数]之前执行
* <b>注意点:前置认证函数将不受 includeList 与 excludeList 的限制,所有路由的请求都会进入 beforeAuth</b>
*/
public SaFilterAuthStrategy beforeAuth = r -> {};
@Override
public SaServletFilter setAuth(SaFilterAuthStrategy auth) {
this.auth = auth;
return this;
}
@Override
public SaServletFilter setError(SaFilterErrorStrategy error) {
this.error = error;
return this;
}
@Override
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 {
// 执行全局过滤器
beforeAuth.run(null);
SaRouter.match(includeList).notMatch(excludeList).check(r -> {
auth.run(null);
});
}
catch (StopMatchException ignored) {}
catch (BackResultException e) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
return;
}
catch (Throwable e) {
SaJakartaServletOperateUtil.writeResult(response, String.valueOf(error.run(e)));
return;
}
// 执行
chain.doFilter(request, response);
}
}

View File

@@ -1,46 +0,0 @@
/*
* 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.filter;
import cn.dev33.satoken.servlet.util.SaTokenContextJakartaServletUtil;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.core.annotation.Order;
import java.io.IOException;
/**
* SaTokenContext 上下文初始化过滤器 (基于 Jakarta-Servlet)
*
* @author click33
* @since 1.42.0
*/
@Order(SaTokenConsts.SA_TOKEN_CONTEXT_FILTER_ORDER)
public class SaTokenContextFilterForJakartaServlet implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
SaTokenContextJakartaServletUtil.setContext((HttpServletRequest) request, (HttpServletResponse) response);
chain.doFilter(request, response);
} finally {
SaTokenContextJakartaServletUtil.clearContext();
}
}
}

View File

@@ -1,55 +0,0 @@
/*
* 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.filter;
import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.context.model.SaTokenContextModelBox;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.servlet.util.SaJakartaServletOperateUtil;
import cn.dev33.satoken.strategy.SaStrategy;
import cn.dev33.satoken.util.SaTokenConsts;
import jakarta.servlet.*;
import org.springframework.core.annotation.Order;
import java.io.IOException;
/**
* CORS 跨域策略过滤器 (基于 Jakarta-Servlet)
*
* @author click33
* @since 1.42.0
*/
@Order(SaTokenConsts.CORS_FILTER_ORDER)
public class SaTokenCorsFilterForJakartaServlet implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
SaTokenContextModelBox box = SaHolder.getContext().getModelBox();
SaStrategy.instance.corsHandle.execute(box.getRequest(), box.getResponse(), box.getStorage());
}
catch (StopMatchException ignored) {}
catch (BackResultException e) {
SaJakartaServletOperateUtil.writeResult(response, e.getMessage());
return;
}
chain.doFilter(request, response);
}
}

View File

@@ -1,122 +0,0 @@
/*
* 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.interceptor;
import cn.dev33.satoken.exception.BackResultException;
import cn.dev33.satoken.exception.StopMatchException;
import cn.dev33.satoken.fun.SaParamFunction;
import cn.dev33.satoken.strategy.SaAnnotationStrategy;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import java.lang.reflect.Method;
/**
* Sa-Token 综合拦截器,提供注解鉴权和路由拦截鉴权能力
*
* @author click33
* @since 1.34.0
*/
public class SaInterceptor implements HandlerInterceptor {
/**
* 是否打开注解鉴权
*/
public boolean isAnnotation = true;
/**
* 认证函数:每次请求执行
* <p> 参数:路由处理函数指针
*/
public SaParamFunction<Object> auth = handler -> {};
/**
* 创建一个 Sa-Token 综合拦截器,默认带有注解鉴权能力
*/
public SaInterceptor() {
}
/**
* 创建一个 Sa-Token 综合拦截器,默认带有注解鉴权能力
* @param auth 认证函数,每次请求执行
*/
public SaInterceptor(SaParamFunction<Object> auth) {
this.auth = auth;
}
/**
* 设置是否打开注解鉴权
* @param isAnnotation /
* @return 对象自身
*/
public SaInterceptor isAnnotation(boolean isAnnotation) {
this.isAnnotation = isAnnotation;
return this;
}
/**
* 写入[认证函数]: 每次请求执行
* @param auth /
* @return 对象自身
*/
public SaInterceptor setAuth(SaParamFunction<Object> auth) {
this.auth = auth;
return this;
}
// ----------------- 验证方法 -----------------
/**
* 每次请求之前触发的方法
*/
@Override
@SuppressWarnings("all")
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
try {
// 这里必须确保 handler 是 HandlerMethod 类型时,才能进行注解鉴权
if(isAnnotation && handler instanceof HandlerMethod) {
Method method = ((HandlerMethod) handler).getMethod();
SaAnnotationStrategy.instance.checkMethodAnnotation.accept(method);
}
// Auth 校验
auth.run(handler);
} catch (StopMatchException e) {
// StopMatchException 异常代表停止匹配进入Controller
} catch (BackResultException e) {
// BackResultException 异常代表:停止匹配,向前端输出结果
// 请注意此处默认 Content-Type 为 text/plain如果需要返回 JSON 信息,需要在 back 前自行设置 Content-Type 为 application/json
// 例如SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
if(response.getContentType() == null) {
response.setContentType("text/plain; charset=utf-8");
}
response.getWriter().print(e.getMessage());
return false;
}
// 通过验证
return true;
}
}

View File

@@ -1,68 +0,0 @@
/*
* 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.spring;
import cn.dev33.satoken.context.SaTokenContextForReadOnly;
import cn.dev33.satoken.context.model.SaRequest;
import cn.dev33.satoken.context.model.SaResponse;
import cn.dev33.satoken.context.model.SaStorage;
import cn.dev33.satoken.servlet.model.SaRequestForServlet;
import cn.dev33.satoken.servlet.model.SaResponseForServlet;
import cn.dev33.satoken.servlet.model.SaStorageForServlet;
/**
* <h2> 此为低版本(<1.42.0) 的上下文处理方案,基于 Spring 内部工具类 RequestContextHolder 读写上下文,仅做留档,如无必要请勿使用 </h2>
*
* Sa-Token 上下文处理器 [ SpringBoot4 Jakarta Servlet 版 ],在 SpringBoot4 中使用 Sa-Token 时,必须注入此实现类,否则会出现上下文无效异常
*
* @author click33
* @since 1.34.0
*/
public class SaTokenContextForSpringInJakartaServlet implements SaTokenContextForReadOnly {
/**
* 获取当前请求的 Request 包装对象
*/
@Override
public SaRequest getRequest() {
return new SaRequestForServlet(SpringMVCUtil.getRequest());
}
/**
* 获取当前请求的 Response 包装对象
*/
@Override
public SaResponse getResponse() {
return new SaResponseForServlet(SpringMVCUtil.getResponse());
}
/**
* 获取当前请求的 Storage 包装对象
*/
@Override
public SaStorage getStorage() {
return new SaStorageForServlet(SpringMVCUtil.getRequest());
}
/**
* 判断:在本次请求中,此上下文是否可用。
*/
@Override
public boolean isValid() {
return SpringMVCUtil.isWeb();
}
}

View File

@@ -1,70 +0,0 @@
/*
* 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.spring;
import cn.dev33.satoken.filter.SaFirewallCheckFilterForJakartaServlet;
import cn.dev33.satoken.filter.SaTokenContextFilterForJakartaServlet;
import cn.dev33.satoken.filter.SaTokenCorsFilterForJakartaServlet;
import cn.dev33.satoken.spring.pathmatch.SaPathPatternParserUtil;
import cn.dev33.satoken.strategy.SaStrategy;
import org.springframework.context.annotation.Bean;
/**
* 注册 Sa-Token 框架所需要的 Bean
*
* @author click33
* @since 1.34.0
*/
public class SaTokenContextRegister {
public SaTokenContextRegister() {
// 重写路由匹配算法
SaStrategy.instance.routeMatcher = (pattern, path) -> {
return SaPathPatternParserUtil.match(pattern, path);
};
}
/**
* 上下文过滤器
*
* @return /
*/
@Bean
public SaTokenContextFilterForJakartaServlet saTokenContextFilterForServlet() {
return new SaTokenContextFilterForJakartaServlet();
}
/**
* CORS 跨域策略过滤器
*
* @return /
*/
@Bean
public SaTokenCorsFilterForJakartaServlet saTokenCorsFilterForJakartaServlet() {
return new SaTokenCorsFilterForJakartaServlet();
}
/**
* 防火墙过滤器
*
* @return /
*/
@Bean
public SaFirewallCheckFilterForJakartaServlet saFirewallCheckFilterForJakartaServlet() {
return new SaFirewallCheckFilterForJakartaServlet();
}
}

View File

@@ -1,67 +0,0 @@
/*
* 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.spring;
import cn.dev33.satoken.exception.NotWebContextException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
/**
* SpringMVC 相关操作工具类,快速获取当前会话的 HttpServletRequest、HttpServletResponse 对象
*
* @author click33
* @since 1.34.0
*/
public class SpringMVCUtil {
private SpringMVCUtil() {
}
/**
* 获取当前会话的 request
* @return request
*/
public static HttpServletRequest getRequest() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(servletRequestAttributes == null) {
throw new NotWebContextException("非 web 上下文无法获取 HttpServletRequest");
}
return servletRequestAttributes.getRequest();
}
/**
* 获取当前会话的 response
* @return response
*/
public static HttpServletResponse getResponse() {
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
if(servletRequestAttributes == null) {
throw new NotWebContextException("非 web 上下文无法获取 HttpServletRequest");
}
return servletRequestAttributes.getResponse();
}
/**
* 判断当前是否处于 Web 上下文中
* @return request
*/
public static boolean isWeb() {
return RequestContextHolder.getRequestAttributes() != null;
}
}

View File

@@ -43,6 +43,7 @@
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<version>2.5.12</version>
<optional>true</optional>
</dependency>
</dependencies>