mirror of
https://gitee.com/dromara/sa-token.git
synced 2025-09-19 01:58:05 +08:00
适配 springboot3
This commit is contained in:
@@ -19,8 +19,12 @@
|
||||
<!-- 所有子模块 -->
|
||||
<modules>
|
||||
<module>sa-token-servlet</module>
|
||||
<module>sa-token-jakarta-servlet</module>
|
||||
<module>sa-token-spring-boot-autoconfig</module>
|
||||
<module>sa-token-spring-boot-starter</module>
|
||||
<module>sa-token-spring-boot3-starter</module>
|
||||
<module>sa-token-reactor-spring-boot-starter</module>
|
||||
<module>sa-token-reactor-spring-boot3-starter</module>
|
||||
<module>sa-token-solon-plugin</module>
|
||||
<module>sa-token-jboot-plugin</module>
|
||||
<module>sa-token-jfinal-plugin</module>
|
||||
|
12
sa-token-starter/sa-token-jakarta-servlet/.gitignore
vendored
Normal file
12
sa-token-starter/sa-token-jakarta-servlet/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
target/
|
||||
|
||||
node_modules/
|
||||
bin/
|
||||
.settings/
|
||||
unpackage/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
.factorypath
|
||||
|
||||
.idea/
|
35
sa-token-starter/sa-token-jakarta-servlet/pom.xml
Normal file
35
sa-token-starter/sa-token-jakarta-servlet/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?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-jakarta-servlet</name>
|
||||
<artifactId>sa-token-jakarta-servlet</artifactId>
|
||||
<description>sa-token authentication by Jakarta Servlet API</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- sa-token-core -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- Servlet API -->
|
||||
<dependency>
|
||||
<groupId>jakarta.servlet</groupId>
|
||||
<artifactId>jakarta.servlet-api</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
</project>
|
@@ -0,0 +1,17 @@
|
||||
package cn.dev33.satoken.servlet.error;
|
||||
|
||||
/**
|
||||
* 定义 sa-token-servlet 所有异常细分状态码
|
||||
*
|
||||
* @author kong
|
||||
* @since: 2022-10-30
|
||||
*/
|
||||
public interface SaServletErrorCode {
|
||||
|
||||
/** 转发失败 */
|
||||
public static final int CODE_20001 = 20001;
|
||||
|
||||
/** 重定向失败 */
|
||||
public static final int CODE_20002 = 20002;
|
||||
|
||||
}
|
@@ -0,0 +1,117 @@
|
||||
package cn.dev33.satoken.servlet.model;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.context.model.SaRequest;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.servlet.error.SaServletErrorCode;
|
||||
import cn.dev33.satoken.util.SaFoxUtil;
|
||||
import jakarta.servlet.ServletException;
|
||||
import jakarta.servlet.http.Cookie;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Request for Jakarta Servlet
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaRequestForServlet implements SaRequest {
|
||||
|
||||
/**
|
||||
* 底层Request对象
|
||||
*/
|
||||
protected HttpServletRequest request;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
* @param request request对象
|
||||
*/
|
||||
public SaRequestForServlet(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取底层源对象
|
||||
*/
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 [请求体] 里获取一个值
|
||||
*/
|
||||
@Override
|
||||
public String getParam(String name) {
|
||||
return request.getParameter(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 [请求头] 里获取一个值
|
||||
*/
|
||||
@Override
|
||||
public String getHeader(String name) {
|
||||
return request.getHeader(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 [Cookie作用域] 里获取一个值
|
||||
*/
|
||||
@Override
|
||||
public String getCookieValue(String name) {
|
||||
Cookie[] cookies = request.getCookies();
|
||||
if (cookies != null) {
|
||||
for (Cookie cookie : cookies) {
|
||||
if (cookie != null && name.equals(cookie.getName())) {
|
||||
return cookie.getValue();
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前请求path (不包括上下文名称)
|
||||
*/
|
||||
@Override
|
||||
public String getRequestPath() {
|
||||
return request.getServletPath();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前请求的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.getRequestURL().toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回当前请求的类型
|
||||
*/
|
||||
@Override
|
||||
public String getMethod() {
|
||||
return request.getMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* 转发请求
|
||||
*/
|
||||
@Override
|
||||
public Object forward(String path) {
|
||||
try {
|
||||
HttpServletResponse response = (HttpServletResponse)SaManager.getSaTokenContextOrSecond().getResponse().getSource();
|
||||
request.getRequestDispatcher(path).forward(request, response);
|
||||
return null;
|
||||
} catch (ServletException | IOException e) {
|
||||
throw new SaTokenException(e).setCode(SaServletErrorCode.CODE_20001);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,79 @@
|
||||
package cn.dev33.satoken.servlet.model;
|
||||
|
||||
import cn.dev33.satoken.context.model.SaResponse;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.servlet.error.SaServletErrorCode;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* Response for Jakarta Servlet
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaResponseForServlet implements SaResponse {
|
||||
|
||||
/**
|
||||
* 底层Request对象
|
||||
*/
|
||||
protected HttpServletResponse response;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
* @param response response对象
|
||||
*/
|
||||
public SaResponseForServlet(HttpServletResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取底层源对象
|
||||
*/
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return response;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置响应状态码
|
||||
*/
|
||||
@Override
|
||||
public SaResponse setStatus(int sc) {
|
||||
response.setStatus(sc);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在响应头里写入一个值
|
||||
*/
|
||||
@Override
|
||||
public SaResponse setHeader(String name, String value) {
|
||||
response.setHeader(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在响应头里添加一个值
|
||||
* @param name 名字
|
||||
* @param value 值
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaResponse addHeader(String name, String value) {
|
||||
response.addHeader(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 重定向
|
||||
*/
|
||||
@Override
|
||||
public Object redirect(String url) {
|
||||
try {
|
||||
response.sendRedirect(url);
|
||||
} catch (Exception e) {
|
||||
throw new SaTokenException(e).setCode(SaServletErrorCode.CODE_20002);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,60 @@
|
||||
package cn.dev33.satoken.servlet.model;
|
||||
|
||||
import cn.dev33.satoken.context.model.SaStorage;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Storage for Jakarta Servlet
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaStorageForServlet implements SaStorage {
|
||||
|
||||
/**
|
||||
* 底层Request对象
|
||||
*/
|
||||
protected HttpServletRequest request;
|
||||
|
||||
/**
|
||||
* 实例化
|
||||
* @param request request对象
|
||||
*/
|
||||
public SaStorageForServlet(HttpServletRequest request) {
|
||||
this.request = request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取底层源对象
|
||||
*/
|
||||
@Override
|
||||
public Object getSource() {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 [Request作用域] 里写入一个值
|
||||
*/
|
||||
@Override
|
||||
public SaStorageForServlet set(String key, Object value) {
|
||||
request.setAttribute(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 [Request作用域] 里获取一个值
|
||||
*/
|
||||
@Override
|
||||
public Object get(String key) {
|
||||
return request.getAttribute(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在 [Request作用域] 里删除一个值
|
||||
*/
|
||||
@Override
|
||||
public SaStorageForServlet delete(String key) {
|
||||
request.removeAttribute(key);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Sa-Token对接ServletAPI容器所需要的实现类接口包
|
||||
*/
|
||||
package cn.dev33.satoken.servlet;
|
@@ -17,12 +17,6 @@
|
||||
<description>springboot reactor integrate sa-token</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- sa-token-core -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-boot-starter (optional) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -34,7 +28,6 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>6.0.0</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -59,20 +52,18 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- OAuth2.0 (optional) -->
|
||||
<!-- sa-token-core -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-oauth2</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- SSO (optional) -->
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token-spring-boot-autoconfig -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-sso</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
@@ -81,5 +72,17 @@
|
||||
</dependencies>
|
||||
|
||||
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>5.3.7</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
|
||||
</project>
|
||||
|
@@ -1,186 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.util.PathMatcher;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.basic.SaBasicTemplate;
|
||||
import cn.dev33.satoken.basic.SaBasicUtil;
|
||||
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;
|
||||
import cn.dev33.satoken.log.SaLog;
|
||||
import cn.dev33.satoken.same.SaSameTemplate;
|
||||
import cn.dev33.satoken.sign.SaSignTemplate;
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpLogic;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.dev33.satoken.temp.SaTempInterface;
|
||||
|
||||
/**
|
||||
* 利用spring的自动装配来加载开发者重写的Bean
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class SaBeanInject {
|
||||
|
||||
/**
|
||||
* 组件注入
|
||||
* <p> 为确保 Log 组件正常打印,必须将 SaLog 和 SaTokenConfig 率先初始化 </p>
|
||||
*
|
||||
* @param saTokenConfig 配置对象
|
||||
*/
|
||||
public SaBeanInject(
|
||||
@Autowired(required = false) SaLog log,
|
||||
@Autowired(required = false) SaTokenConfig saTokenConfig
|
||||
){
|
||||
if(log != null) {
|
||||
SaManager.setLog(log);
|
||||
}
|
||||
if(saTokenConfig != null) {
|
||||
SaManager.setConfig(saTokenConfig);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入持久化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 saTokenSecondContextCreator 二级上下文创建器
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaTokenContext(SaTokenSecondContextCreator saTokenSecondContextCreator) {
|
||||
SaManager.setSaTokenSecondContext(saTokenSecondContextCreator.create());
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入侦听器Bean
|
||||
*
|
||||
* @param listenerList 侦听器集合
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaTokenListener(List<SaTokenListener> listenerList) {
|
||||
SaTokenEventCenter.registerListenerList(listenerList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入临时令牌验证模块 Bean
|
||||
*
|
||||
* @param saTemp saTemp对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaTemp(SaTempInterface saTemp) {
|
||||
SaManager.setSaTemp(saTemp);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 Sa-Id-Token 模块 Bean
|
||||
*
|
||||
* @param saIdTemplate saIdTemplate对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaIdTemplate(SaIdTemplate saIdTemplate) {
|
||||
SaIdUtil.saIdTemplate = saIdTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 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 setSaBasicTemplate(SaBasicTemplate saBasicTemplate) {
|
||||
SaBasicUtil.saBasicTemplate = saBasicTemplate;
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入自定义的 JSON 转换器 Bean
|
||||
*
|
||||
* @param saJsonTemplate JSON 转换器
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaJsonTemplate(SaJsonTemplate saJsonTemplate) {
|
||||
SaManager.setSaJsonTemplate(saJsonTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入自定义的 参数签名 Bean
|
||||
*
|
||||
* @param saSignTemplate 参数签名 Bean
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaSignTemplate(SaSignTemplate saSignTemplate) {
|
||||
SaManager.setSaSignTemplate(saSignTemplate);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入自定义的 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);
|
||||
}
|
||||
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring;
|
||||
|
||||
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.reactor.spring.json.SaJsonTemplateForJackson;
|
||||
|
||||
/**
|
||||
* 注册Sa-Token所需要的Bean
|
||||
* <p> Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaBeanRegister {
|
||||
|
||||
/**
|
||||
* 获取配置Bean
|
||||
*
|
||||
* @return 配置对象
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "sa-token")
|
||||
public SaTokenConfig getSaTokenConfig() {
|
||||
return new SaTokenConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取容器交互Bean (ThreadLocal版)
|
||||
*
|
||||
* @return 容器交互Bean (ThreadLocal版)
|
||||
*/
|
||||
@Bean
|
||||
public SaTokenContext getSaTokenContext() {
|
||||
return new SaTokenContextForSpringReactor();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 json 转换器 Bean (Jackson版)
|
||||
*
|
||||
* @return json 转换器 Bean (Jackson版)
|
||||
*/
|
||||
@Bean
|
||||
public SaJsonTemplate getSaJsonTemplateForJackson() {
|
||||
return new SaJsonTemplateForJackson();
|
||||
}
|
||||
|
||||
}
|
@@ -1,37 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring;
|
||||
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
import org.springframework.util.PathMatcher;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class 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;
|
||||
}
|
||||
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
package cn.dev33.satoken.reactor.spring;
|
||||
|
||||
import cn.dev33.satoken.context.SaTokenContextForThreadLocal;
|
||||
import cn.dev33.satoken.spring.SaPathMatcherHolder;
|
||||
|
||||
/**
|
||||
* Sa-Token 上下文处理器 [ Spring Reactor 版本实现 ]
|
||||
|
@@ -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
|
||||
* <p> Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenContextRegister {
|
||||
|
||||
/**
|
||||
* 获取容器交互Bean (ThreadLocal版)
|
||||
*
|
||||
* @return 容器交互Bean (ThreadLocal版)
|
||||
*/
|
||||
@Bean
|
||||
public SaTokenContext getSaTokenContextForSpringReactor() {
|
||||
return new SaTokenContextForSpringReactor();
|
||||
}
|
||||
|
||||
}
|
@@ -1,53 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring.json;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
import cn.dev33.satoken.exception.SaJsonConvertException;
|
||||
import cn.dev33.satoken.json.SaJsonTemplate;
|
||||
import cn.dev33.satoken.reactor.error.SaReactorSpringBootErrorCode;
|
||||
|
||||
/**
|
||||
* JSON 转换器, Jackson 版实现
|
||||
*
|
||||
* @author kong
|
||||
* @since: 2022-4-26
|
||||
*/
|
||||
public class SaJsonTemplateForJackson implements SaJsonTemplate {
|
||||
|
||||
/**
|
||||
* 底层 Mapper 对象
|
||||
*/
|
||||
public ObjectMapper objectMapper = new ObjectMapper();
|
||||
|
||||
/**
|
||||
* 将任意对象转换为 json 字符串
|
||||
*
|
||||
* @param obj 对象
|
||||
* @return 转换后的 json 字符串
|
||||
*/
|
||||
public String toJsonString(Object obj) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(obj);
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new SaJsonConvertException(e).setCode(SaReactorSpringBootErrorCode.CODE_20203);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 json 字符串解析为 Map
|
||||
*/
|
||||
@Override
|
||||
public Map<String, Object> parseJsonToMap(String jsonStr) {
|
||||
try {
|
||||
@SuppressWarnings("unchecked")
|
||||
Map<String, Object> map = objectMapper.readValue(jsonStr, Map.class);
|
||||
return map;
|
||||
} catch (JsonProcessingException e) {
|
||||
throw new SaJsonConvertException(e).setCode(SaReactorSpringBootErrorCode.CODE_20204);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -1,40 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring.oauth2;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
|
||||
import cn.dev33.satoken.oauth2.logic.SaOAuth2Template;
|
||||
import cn.dev33.satoken.oauth2.logic.SaOAuth2Util;
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-OAuth2 所需要的Bean
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@ConditionalOnClass(SaOAuth2Manager.class)
|
||||
public class SaOAuth2BeanInject {
|
||||
|
||||
/**
|
||||
* 注入OAuth2配置Bean
|
||||
*
|
||||
* @param saOAuth2Config 配置对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaOAuth2Config(SaOAuth2Config saOAuth2Config) {
|
||||
SaOAuth2Manager.setConfig(saOAuth2Config);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入代码模板Bean
|
||||
*
|
||||
* @param saOAuth2Template 代码模板Bean
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaOAuth2Interface(SaOAuth2Template saOAuth2Template) {
|
||||
SaOAuth2Util.saOAuth2Template = saOAuth2Template;
|
||||
}
|
||||
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring.oauth2;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import cn.dev33.satoken.oauth2.SaOAuth2Manager;
|
||||
import cn.dev33.satoken.oauth2.config.SaOAuth2Config;
|
||||
|
||||
/**
|
||||
* 注册 Sa-Token-OAuth2 所需要的Bean
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@ConditionalOnClass(SaOAuth2Manager.class)
|
||||
public class SaOAuth2BeanRegister {
|
||||
|
||||
/**
|
||||
* 获取OAuth2配置Bean
|
||||
* @return 配置对象
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "sa-token.oauth2")
|
||||
public SaOAuth2Config getSaOAuth2Config() {
|
||||
return new SaOAuth2Config();
|
||||
}
|
||||
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Sa-Token-OAuth2 模块自动化配置(只有引入了Sa-Token-OAuth2模块后,此包下的代码才会开始工作)
|
||||
*/
|
||||
package cn.dev33.satoken.reactor.spring.oauth2;
|
@@ -1,40 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring.sso;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
|
||||
import cn.dev33.satoken.config.SaSsoConfig;
|
||||
import cn.dev33.satoken.sso.SaSsoManager;
|
||||
import cn.dev33.satoken.sso.SaSsoTemplate;
|
||||
import cn.dev33.satoken.sso.SaSsoUtil;
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-SSO 所需要的Bean
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@ConditionalOnClass(SaSsoManager.class)
|
||||
public class SaSsoBeanInject {
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-SSO 配置Bean
|
||||
*
|
||||
* @param saSsoConfig 配置对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaOAuth2Config(SaSsoConfig saSsoConfig) {
|
||||
SaSsoManager.setConfig(saSsoConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 注入 Sa-Token-SSO 单点登录模块 Bean
|
||||
*
|
||||
* @param saSsoTemplate saSsoTemplate对象
|
||||
*/
|
||||
@Autowired(required = false)
|
||||
public void setSaSsoTemplate(SaSsoTemplate saSsoTemplate) {
|
||||
SaSsoUtil.ssoTemplate = saSsoTemplate;
|
||||
}
|
||||
|
||||
}
|
@@ -1,28 +0,0 @@
|
||||
package cn.dev33.satoken.reactor.spring.sso;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import cn.dev33.satoken.config.SaSsoConfig;
|
||||
import cn.dev33.satoken.sso.SaSsoManager;
|
||||
|
||||
/**
|
||||
* 注册 Sa-Token-SSO 所需要的Bean
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@ConditionalOnClass(SaSsoManager.class)
|
||||
public class SaSsoBeanRegister {
|
||||
|
||||
/**
|
||||
* 获取 SSO 配置Bean
|
||||
* @return 配置对象
|
||||
*/
|
||||
@Bean
|
||||
@ConfigurationProperties(prefix = "sa-token.sso")
|
||||
public SaSsoConfig getSaSsoConfig() {
|
||||
return new SaSsoConfig();
|
||||
}
|
||||
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* Sa-Token-SSO 模块自动化配置(只有引入了 sa-token-sso 模块后,此包下的代码才会开始工作)
|
||||
*/
|
||||
package cn.dev33.satoken.reactor.spring.sso;
|
@@ -1,7 +1,2 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
cn.dev33.satoken.reactor.spring.SaBeanRegister,\
|
||||
cn.dev33.satoken.reactor.spring.SaBeanInject,\
|
||||
cn.dev33.satoken.reactor.spring.sso.SaSsoBeanRegister,\
|
||||
cn.dev33.satoken.reactor.spring.sso.SaSsoBeanInject,\
|
||||
cn.dev33.satoken.reactor.spring.oauth2.SaOAuth2BeanRegister,\
|
||||
cn.dev33.satoken.reactor.spring.oauth2.SaOAuth2BeanInject
|
||||
cn.dev33.satoken.reactor.spring.SaTokenContextRegister
|
12
sa-token-starter/sa-token-reactor-spring-boot3-starter/.gitignore
vendored
Normal file
12
sa-token-starter/sa-token-reactor-spring-boot3-starter/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
target/
|
||||
|
||||
node_modules/
|
||||
bin/
|
||||
.settings/
|
||||
unpackage/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
.factorypath
|
||||
|
||||
.idea/
|
118
sa-token-starter/sa-token-reactor-spring-boot3-starter/pom.xml
Normal file
118
sa-token-starter/sa-token-reactor-spring-boot3-starter/pom.xml
Normal file
@@ -0,0 +1,118 @@
|
||||
<?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-reactor-spring-boot3-starter</name>
|
||||
<artifactId>sa-token-reactor-spring-boot3-starter</artifactId>
|
||||
<description>springboot3 reactor integrate sa-token</description>
|
||||
|
||||
<properties>
|
||||
<springboot3.version>3.0.1</springboot3.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<!-- spring-boot-starter (optional) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-web (optional) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<!--<version>5.3.7</version>-->
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- reactor-core (optional) -->
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson-databind (optional) -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- config -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token-core -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token-spring-boot-autoconfig -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-webflux</artifactId>
|
||||
<version>${springboot.version}</version>
|
||||
</dependency> -->
|
||||
</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 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-web</artifactId>
|
||||
<version>6.0.0</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>io.projectreactor</groupId>
|
||||
<artifactId>reactor-core</artifactId>
|
||||
<version>3.5.1</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>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<version>${springboot3.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
</project>
|
@@ -0,0 +1,49 @@
|
||||
package cn.dev33.satoken.reactor.context;
|
||||
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Reactor上下文操作 [异步]
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaReactorHolder {
|
||||
|
||||
/**
|
||||
* key
|
||||
*/
|
||||
public static final Class<ServerWebExchange> CONTEXT_KEY = ServerWebExchange.class;
|
||||
|
||||
/**
|
||||
* chain_key
|
||||
*/
|
||||
public static final String CHAIN_KEY = "WEB_FILTER_CHAIN_KEY";
|
||||
|
||||
/**
|
||||
* 获取上下文对象
|
||||
* @return see note
|
||||
*/
|
||||
public static Mono<ServerWebExchange> getContext() {
|
||||
// 从全局 Mono<Context> 获取
|
||||
return Mono.deferContextual(Mono::just).map(ctx -> ctx.get(CONTEXT_KEY));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文对象, 并设置到同步上下文中
|
||||
* @return see note
|
||||
*/
|
||||
public static Mono<ServerWebExchange> getContextAndSetSync() {
|
||||
// 从全局 Mono<Context> 获取
|
||||
return Mono.deferContextual(Mono::just).map(ctx -> {
|
||||
// 设置到sync中
|
||||
SaReactorSyncHolder.setContext(ctx.get(CONTEXT_KEY));
|
||||
return ctx.get(CONTEXT_KEY);
|
||||
}).doFinally(r->{
|
||||
// 从sync中清除
|
||||
SaReactorSyncHolder.clearContext();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,63 @@
|
||||
package cn.dev33.satoken.reactor.context;
|
||||
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
|
||||
import cn.dev33.satoken.context.SaTokenContextForThreadLocalStorage;
|
||||
import cn.dev33.satoken.context.SaTokenContextForThreadLocalStorage.Box;
|
||||
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.fun.SaFunction;
|
||||
import cn.dev33.satoken.reactor.model.SaRequestForReactor;
|
||||
import cn.dev33.satoken.reactor.model.SaResponseForReactor;
|
||||
import cn.dev33.satoken.reactor.model.SaStorageForReactor;
|
||||
|
||||
/**
|
||||
* Reactor上下文操作 [同步]
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaReactorSyncHolder {
|
||||
|
||||
/**
|
||||
* 写入上下文对象
|
||||
* @param exchange see note
|
||||
*/
|
||||
public static void setContext(ServerWebExchange exchange) {
|
||||
SaRequest request = new SaRequestForReactor(exchange.getRequest());
|
||||
SaResponse response = new SaResponseForReactor(exchange.getResponse());
|
||||
SaStorage storage = new SaStorageForReactor(exchange);
|
||||
SaTokenContextForThreadLocalStorage.setBox(request, response, storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取上下文对象
|
||||
* @return see note
|
||||
*/
|
||||
public static ServerWebExchange getContext() {
|
||||
Box box = SaTokenContextForThreadLocalStorage.getBoxNotNull();
|
||||
return (ServerWebExchange)box.getStorage().getSource();
|
||||
}
|
||||
|
||||
/**
|
||||
* 清除上下文对象
|
||||
*/
|
||||
public static void clearContext() {
|
||||
SaTokenContextForThreadLocalStorage.clearBox();
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入上下文对象, 并在执行函数后将其清除
|
||||
* @param exchange see note
|
||||
* @param fun see note
|
||||
*/
|
||||
public static void setContext(ServerWebExchange exchange, SaFunction fun) {
|
||||
try {
|
||||
setContext(exchange);
|
||||
fun.run();
|
||||
} finally {
|
||||
clearContext();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
package cn.dev33.satoken.reactor.error;
|
||||
|
||||
/**
|
||||
* 定义 sa-token-reactor-spring-boot-starter 所有异常细分状态码
|
||||
*
|
||||
* @author kong
|
||||
* @since: 2022-10-30
|
||||
*/
|
||||
public interface SaReactorSpringBootErrorCode {
|
||||
|
||||
/** 对象转 JSON 字符串失败 */
|
||||
public static final int CODE_20203 = 20203;
|
||||
|
||||
/** JSON 字符串转 Map 失败 */
|
||||
public static final int CODE_20204 = 20204;
|
||||
|
||||
/** 默认的 Filter 异常处理函数 */
|
||||
public static final int CODE_20205 = 20205;
|
||||
|
||||
}
|
@@ -0,0 +1,203 @@
|
||||
package cn.dev33.satoken.reactor.filter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.web.server.ServerWebExchange;
|
||||
import org.springframework.web.server.WebFilter;
|
||||
import org.springframework.web.server.WebFilterChain;
|
||||
|
||||
import cn.dev33.satoken.exception.BackResultException;
|
||||
import cn.dev33.satoken.exception.SaTokenException;
|
||||
import cn.dev33.satoken.exception.StopMatchException;
|
||||
import cn.dev33.satoken.filter.SaFilterAuthStrategy;
|
||||
import cn.dev33.satoken.filter.SaFilterErrorStrategy;
|
||||
import cn.dev33.satoken.reactor.context.SaReactorHolder;
|
||||
import cn.dev33.satoken.reactor.context.SaReactorSyncHolder;
|
||||
import cn.dev33.satoken.reactor.error.SaReactorSpringBootErrorCode;
|
||||
import cn.dev33.satoken.router.SaRouter;
|
||||
import cn.dev33.satoken.util.SaTokenConsts;
|
||||
import reactor.core.publisher.Mono;
|
||||
|
||||
/**
|
||||
* Reactor全局过滤器
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
@Order(SaTokenConsts.ASSEMBLY_ORDER)
|
||||
public class SaReactorFilter implements WebFilter {
|
||||
|
||||
// ------------------------ 设置此过滤器 拦截 & 放行 的路由
|
||||
|
||||
/**
|
||||
* 拦截路由
|
||||
*/
|
||||
private List<String> includeList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 放行路由
|
||||
*/
|
||||
private List<String> excludeList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 添加 [拦截路由]
|
||||
* @param paths 路由
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter addInclude(String... paths) {
|
||||
includeList.addAll(Arrays.asList(paths));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加 [放行路由]
|
||||
* @param paths 路由
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter addExclude(String... paths) {
|
||||
excludeList.addAll(Arrays.asList(paths));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 [拦截路由] 集合
|
||||
* @param pathList 路由集合
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter setIncludeList(List<String> pathList) {
|
||||
includeList = pathList;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 [放行路由] 集合
|
||||
* @param pathList 路由集合
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter setExcludeList(List<String> pathList) {
|
||||
excludeList = pathList;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [拦截路由] 集合
|
||||
* @return see note
|
||||
*/
|
||||
public List<String> getIncludeList() {
|
||||
return includeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [放行路由] 集合
|
||||
* @return see note
|
||||
*/
|
||||
public List<String> getExcludeList() {
|
||||
return excludeList;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------ 钩子函数
|
||||
|
||||
/**
|
||||
* 认证函数:每次请求执行
|
||||
*/
|
||||
public SaFilterAuthStrategy auth = r -> {};
|
||||
|
||||
/**
|
||||
* 异常处理函数:每次[认证函数]发生异常时执行此函数
|
||||
*/
|
||||
public SaFilterErrorStrategy error = e -> {
|
||||
throw new SaTokenException(e).setCode(SaReactorSpringBootErrorCode.CODE_20205);
|
||||
};
|
||||
|
||||
/**
|
||||
* 前置函数:在每次[认证函数]之前执行
|
||||
*/
|
||||
public SaFilterAuthStrategy beforeAuth = r -> {};
|
||||
|
||||
/**
|
||||
* 写入[认证函数]: 每次请求执行
|
||||
* @param auth see note
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter setAuth(SaFilterAuthStrategy auth) {
|
||||
this.auth = auth;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入[异常处理函数]:每次[认证函数]发生异常时执行此函数
|
||||
* @param error see note
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter setError(SaFilterErrorStrategy error) {
|
||||
this.error = error;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入[前置函数]:在每次[认证函数]之前执行
|
||||
* @param beforeAuth see note
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaReactorFilter setBeforeAuth(SaFilterAuthStrategy beforeAuth) {
|
||||
this.beforeAuth = beforeAuth;
|
||||
return this;
|
||||
}
|
||||
|
||||
|
||||
// ------------------------ filter
|
||||
|
||||
@Override
|
||||
public Mono<Void> 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();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* sa-token集成Reactor响应式编程的各个组件
|
||||
*/
|
||||
package cn.dev33.satoken.reactor;
|
@@ -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);
|
||||
}
|
||||
|
||||
}
|
@@ -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
|
||||
* <p> Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenContextRegister {
|
||||
|
||||
/**
|
||||
* 获取容器交互Bean (ThreadLocal版)
|
||||
*
|
||||
* @return 容器交互Bean (ThreadLocal版)
|
||||
*/
|
||||
@Bean
|
||||
public SaTokenContext getSaTokenContextForSpringReactor() {
|
||||
return new SaTokenContextForSpringReactor();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
cn.dev33.satoken.reactor.spring.SaTokenContextRegister
|
@@ -14,7 +14,7 @@
|
||||
|
||||
<name>sa-token-servlet</name>
|
||||
<artifactId>sa-token-servlet</artifactId>
|
||||
<description>sa-token authentication by Sservlet API</description>
|
||||
<description>sa-token authentication by Servlet API</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- sa-token-core -->
|
||||
|
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
12
sa-token-starter/sa-token-spring-boot-autoconfig/.gitignore
vendored
Normal file
12
sa-token-starter/sa-token-spring-boot-autoconfig/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
target/
|
||||
|
||||
node_modules/
|
||||
bin/
|
||||
.settings/
|
||||
unpackage/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
.factorypath
|
||||
|
||||
.idea/
|
57
sa-token-starter/sa-token-spring-boot-autoconfig/pom.xml
Normal file
57
sa-token-starter/sa-token-spring-boot-autoconfig/pom.xml
Normal file
@@ -0,0 +1,57 @@
|
||||
<?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-autoconfig</name>
|
||||
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
|
||||
<description>sa-token-spring-boot-autoconfig</description>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- spring-boot-starter (optional) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- config (optional) -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- OAuth2.0 (optional) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-oauth2</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- SSO (optional) -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-sso</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
||||
</project>
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* sa-token集成SpringBoot的各个组件
|
||||
*/
|
||||
package cn.dev33.satoken;
|
@@ -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
|
||||
*
|
@@ -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版)
|
||||
*
|
@@ -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
|
@@ -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
|
@@ -17,12 +17,6 @@
|
||||
<description>springboot integrate sa-token</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- sa-token-core -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-servlet</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- spring-boot-starter-web -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
@@ -36,19 +30,18 @@
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
<!-- OAuth2.0 (optional) -->
|
||||
<!-- sa-token-servlet -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-oauth2</artifactId>
|
||||
<optional>true</optional>
|
||||
<artifactId>sa-token-servlet</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- SSO (optional) -->
|
||||
<!-- sa-token-spring-boot-autoconfig -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-sso</artifactId>
|
||||
<optional>true</optional>
|
||||
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
|
@@ -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 注解式鉴权 - 拦截器
|
||||
* <h2> [ 当前拦截器写法已过期,可能将在以后的版本删除,推荐升级为 SaInterceptor ] </h2>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
@@ -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 拦截式鉴权 - 拦截器
|
||||
* <h2> [ 当前拦截器写法已过期,可能将在以后的版本删除,推荐升级为 SaInterceptor ] </h2>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,25 @@
|
||||
package cn.dev33.satoken.spring;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import cn.dev33.satoken.context.SaTokenContext;
|
||||
|
||||
/**
|
||||
* 注册Sa-Token所需要的Bean
|
||||
* <p> Bean 的注册与注入应该分开在两个文件中,否则在某些场景下会造成循环依赖
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenContextRegister {
|
||||
|
||||
/**
|
||||
* 获取上下文Bean (Spring版)
|
||||
*
|
||||
* @return 容器交互Bean (Spring版)
|
||||
*/
|
||||
@Bean
|
||||
public SaTokenContext getSaTokenContextForSpring() {
|
||||
return new SaTokenContextForSpring();
|
||||
}
|
||||
|
||||
}
|
@@ -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
|
||||
cn.dev33.satoken.spring.SaTokenContextRegister
|
12
sa-token-starter/sa-token-spring-boot3-starter/.gitignore
vendored
Normal file
12
sa-token-starter/sa-token-spring-boot3-starter/.gitignore
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
target/
|
||||
|
||||
node_modules/
|
||||
bin/
|
||||
.settings/
|
||||
unpackage/
|
||||
.classpath
|
||||
.project
|
||||
|
||||
.factorypath
|
||||
|
||||
.idea/
|
77
sa-token-starter/sa-token-spring-boot3-starter/pom.xml
Normal file
77
sa-token-starter/sa-token-spring-boot3-starter/pom.xml
Normal file
@@ -0,0 +1,77 @@
|
||||
<?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-boot3-starter</name>
|
||||
<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 -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-jakarta-servlet</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- sa-token-spring-boot-autoconfig -->
|
||||
<dependency>
|
||||
<groupId>cn.dev33</groupId>
|
||||
<artifactId>sa-token-spring-boot-autoconfig</artifactId>
|
||||
</dependency>
|
||||
|
||||
</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 -->
|
||||
<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>
|
@@ -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<String> includeList = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* 放行路由
|
||||
*/
|
||||
private List<String> 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<String> pathList) {
|
||||
includeList = pathList;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 写入 [放行路由] 集合
|
||||
* @param pathList 路由集合
|
||||
* @return 对象自身
|
||||
*/
|
||||
public SaServletFilter setExcludeList(List<String> pathList) {
|
||||
excludeList = pathList;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [拦截路由] 集合
|
||||
* @return see note
|
||||
*/
|
||||
public List<String> getIncludeList() {
|
||||
return includeList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 [放行路由] 集合
|
||||
* @return see note
|
||||
*/
|
||||
public List<String> 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() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@@ -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;
|
||||
|
||||
/**
|
||||
* 认证函数:每次请求执行
|
||||
* <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
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||
throws Exception {
|
||||
|
||||
try {
|
||||
|
||||
if(isAnnotation && handler instanceof HandlerMethod) {
|
||||
|
||||
// 获取此请求对应的 Method 处理函数
|
||||
Method method = ((HandlerMethod) handler).getMethod();
|
||||
|
||||
// 如果此 Method 或其所属 Class 标注了 @SaIgnore,则忽略掉鉴权
|
||||
if(SaStrategy.me.isAnnotationPresent.apply(method, SaIgnore.class)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// 注解校验
|
||||
SaStrategy.me.checkMethodAnnotation.accept(method);
|
||||
}
|
||||
|
||||
// Auth 校验
|
||||
auth.run(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;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* sa-token集成SpringBoot的各个组件
|
||||
*/
|
||||
package cn.dev33.satoken;
|
@@ -0,0 +1,59 @@
|
||||
package cn.dev33.satoken.spring;
|
||||
|
||||
import cn.dev33.satoken.context.SaTokenContext;
|
||||
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;
|
||||
|
||||
/**
|
||||
* Sa-Token 上下文处理器 [ SpringBoot3 Jakarta Servlet 版 ]
|
||||
*
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SaTokenContextForSpringInJakartaServlet implements SaTokenContext {
|
||||
|
||||
/**
|
||||
* 获取当前请求的Request对象
|
||||
*/
|
||||
@Override
|
||||
public SaRequest getRequest() {
|
||||
return new SaRequestForServlet(SpringMVCUtil.getRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前请求的Response对象
|
||||
*/
|
||||
@Override
|
||||
public SaResponse getResponse() {
|
||||
return new SaResponseForServlet(SpringMVCUtil.getResponse());
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前请求的 [存储器] 对象
|
||||
*/
|
||||
@Override
|
||||
public SaStorage getStorage() {
|
||||
return new SaStorageForServlet(SpringMVCUtil.getRequest());
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验指定路由匹配符是否可以匹配成功指定路径
|
||||
*/
|
||||
@Override
|
||||
public boolean matchPath(String pattern, String path) {
|
||||
return SaPathMatcherHolder.getPathMatcher().match(pattern, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* 此上下文是否有效
|
||||
*/
|
||||
@Override
|
||||
public boolean isValid() {
|
||||
return SpringMVCUtil.isWeb();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,26 @@
|
||||
package cn.dev33.satoken.spring;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
||||
import cn.dev33.satoken.context.SaTokenContext;
|
||||
|
||||
/**
|
||||
* SaTokenContext 上下文注册
|
||||
*
|
||||
* @author kong
|
||||
* @since 2023年1月1日
|
||||
*
|
||||
*/
|
||||
public class SaTokenContextRegister {
|
||||
|
||||
/**
|
||||
* 获取上下文Bean [ SpringBoot3 Jakarta Servlet 版 ]
|
||||
*
|
||||
* @return /
|
||||
*/
|
||||
@Bean
|
||||
public SaTokenContext getSaTokenContextForSpringInJakartaServlet() {
|
||||
return new SaTokenContextForSpringInJakartaServlet();
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,53 @@
|
||||
package cn.dev33.satoken.spring;
|
||||
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
import cn.dev33.satoken.error.SaSpringBootErrorCode;
|
||||
import cn.dev33.satoken.exception.NotWebContextException;
|
||||
import jakarta.servlet.http.HttpServletRequest;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
|
||||
/**
|
||||
* SpringMVC相关操作
|
||||
* @author kong
|
||||
*
|
||||
*/
|
||||
public class SpringMVCUtil {
|
||||
|
||||
private SpringMVCUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的 request
|
||||
* @return request
|
||||
*/
|
||||
public static HttpServletRequest getRequest() {
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if(servletRequestAttributes == null) {
|
||||
throw new NotWebContextException("非Web上下文无法获取Request").setCode(SaSpringBootErrorCode.CODE_20101);
|
||||
}
|
||||
return servletRequestAttributes.getRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取当前会话的 response
|
||||
* @return response
|
||||
*/
|
||||
public static HttpServletResponse getResponse() {
|
||||
ServletRequestAttributes servletRequestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if(servletRequestAttributes == null) {
|
||||
throw new NotWebContextException("非Web上下文无法获取Response").setCode(SaSpringBootErrorCode.CODE_20101);
|
||||
}
|
||||
return servletRequestAttributes.getResponse();
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断当前是否处于 Web 上下文中
|
||||
* @return request
|
||||
*/
|
||||
public static boolean isWeb() {
|
||||
return RequestContextHolder.getRequestAttributes() != null;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1 @@
|
||||
cn.dev33.satoken.spring.SaTokenContextRegister
|
Reference in New Issue
Block a user