Skip to content

Releases: llllllxy/tiny-security

1.4.0版本发布

Choose a tag to compare

@llllllxy llllllxy released this 08 Sep 14:00

1.4.0

升级路径:1.3.3 → 1.4.0 | 本次为双 API 语义统一(破坏性变更)

⚠️ 行为变更(升级必读)

  • AuthUtil / TinySecurityFacade 的 get* 与 has* 系列在未登录/会话失效时统一抛 UnAuthorizedException,不再返回 null:
    • 影响方法:getSecurityContext / getLoginSubject / getLoginId / getLoginIdAsString / getLoginIdAsInt / getLoginIdAsLong / getRoleSet / getPermissionSet / hasRole / hasAllRole / hasAnyRole / hasPermission / hasAllPermission / hasAnyPermission
    • 此前 AuthProvider 系列已抛异常,而 AuthUtil/TinySecurityFacade 系列返回 null,两套 API 行为不一致;本次统一为"未登录即抛异常",与 AuthProvider、Spring Security 语义对齐
    • 破坏性:依赖 AuthUtil.getLoginId() 等返回 null 进行容错判断(如可选鉴权接口、日志埋点)的代码,升级后将抛 UnAuthorizedException,需改为显式捕获或先判断登录状态
  • 移除冗余转发类 SecurityContextUtils(原仅转发到 AuthUtil,无自有逻辑):直接使用 AuthUtil.getSecurityContext() 等替代。破坏性:若外部代码 import 了 SecurityContextUtils,请改用 AuthUtil。
  • 移除冗余转发类 ThreadLocalSecurityContextHolder(原仅封装一个 ThreadLocal):ThreadLocal 已内联进 ThreadLocalSecurityContextRepository,通过其静态方法 getContext() / setContext() / clearContext() 访问。破坏性:若外部代码 import 了 ThreadLocalSecurityContextHolder,请改用 ThreadLocalSecurityContextRepository。
  • 移除冗余抽象 LocalMapContainer 接口及其唯一实现 LocalMapContainerByConcurrentHashMap:LocalTimeCache 的 dataMap/expireMap 字段与构造直接使用 ConcurrentHashMap(底层本就依赖它,行为不变,删除 getSource() 死方法)。破坏性:若外部代码直接 new LocalTimeCache(...),参数类型改为 ConcurrentHashMap<String,Object> / ConcurrentHashMap<String,Long>。
  • SessionRepository.deleteByLoginId 返回值语义统一为"操作已执行"(幂等):此前 Single/Caffeine 无会话时返回 true,而 Jdbc/Redis 返回 false,四个仓储行为不一致。本次统一为:只要操作正常完成即返回 true(无会话可删也算成功,仅异常返回 false)。破坏性:依赖 Jdbc/Redis deleteByLoginId 返回 false 判断"该账号无会话"的代码,升级后将收到 true,请改用 countValidOnlineSessions 判断是否存在会话。

升级检查清单

  • 排查代码中所有 AuthUtil.getLoginId() / AuthUtil.getLoginSubject() / AuthUtil.getSecurityContext() / AuthUtil.getRoleSet() / AuthUtil.getPermissionSet() 及 has* 系列的调用点
  • 若存在"未登录也调用上述方法且依赖返回 null"的场景(如未登录可访问的接口里读取当前用户做日志),改为:先 try { AuthUtil.getLoginId(); } catch (UnAuthorizedException e) { /* 未登录处理 */ },或在确信已登录的路径内调用
  • hasRole / hasPermission 等"判断型"方法:未登录时也会抛异常(不再返回 false)。若希望未登录容错判断,需在调用前确保已登录或显式捕获
  • 全局异常处理器若已处理 UnAuthorizedException(默认 TinySecurityHandlerExceptionResolver 会转为 401),则无需额外改动

新增特性

  • 新增按账号查询会话凭证 getCredentialsByLoginId(Object loginId):返回该账号下全部**有效(未过期)**会话凭证列表,无会话时返回空列表(不返回 null)。
    • 用途:多设备管理(列出账号所有在线设备/会话)、定向下线(配合 deleteByCredentials 只踢指定凭证,而非 deleteByLoginId 全量踢出)
    • 入口:AuthProvider.getCredentialsByLoginId(loginId);四个内置仓储(single / caffeine / redis / jdbc)均已实现
    • 接口方法声明为 default,默认实现抛 UnsupportedOperationException:自定义仓储未实现时显式报错而非静默返回空列表,同时保持存量自定义仓储的编译兼容
    • ⚠️ 安全提示:凭证等同于会话钥匙,请勿写入日志或返回给前端
  • 新增 Caffeine 本地缓存会话仓储(store-type=caffeine):提供容量上限保护(caffeine-maximum-size,默认 10000,近似 LRU 驱逐)与惰性过期驱逐,适合"单机部署、会话量大、需内存上限"场景。
    • 可选依赖:caffeine 以 provided 提供,使用前需自行引入:
      <dependency>
          <groupId>com.github.ben-manes.caffeine</groupId>
          <artifactId>caffeine</artifactId>
      </dependency>
    • 过期语义与其它仓储一致:由 LoginSubject.getLoginExpireTime() 驱动,续期时重新写入即重置。

契约修复

  • getCredentialsByLoginId 返回空列表时统一为可变 ArrayList:此前空列表分支返回 Collections.emptyList()(不可变),非空分支返回 new ArrayList<>(list)(可变),同一份语义却给出不同 mutability(外部 add/remove 会爆 UnsupportedOperationException)。本次将所有内置仓储的空列表分支统一改为 new ArrayList<>(),保证契约一致。

测试加固

  • 新增 AuthProviderCredentialsTest(4 用例):门面透传、空账号返回空列表、logout() 后查询收敛、自定义仓储未实现时抛 UnsupportedOperationException
  • 四个内置仓储测试各 +2 用例:覆盖多凭证返回、过期凭证排除、空账号可变空列表、返回防御性副本

1.3.3

升级路径:1.3.2 → 1.3.3 | 本次为安全加固 + 正确性修复批次(基于 2026-08-31 安全审计)

安全修复

  • 恢复 LoginSubject.toString() 凭证脱敏:1.3.2 后 aae08b7 曾回退为输出真实 credentials(便于排查),现恢复为固定输出 credentials=****,杜绝日志泄露会话凭证;同步恢复并修正 LoginSubjectTest。
  • 移除可预测凭证生成器:删除 snowflake/objectid/ulid 三种凭证风格(含时间戳,凭证可被预测/枚举,存在会话冒充风险),仅保留 uuid/random128/nanoid;CredentialsGenUtil 对未知风格一律回退 uuid。同时删除仅被其引用的 Snowflake/ObjectId/Ulid*/LocalHostUtil 实现。
  • URL 参数 token 默认关闭:新增 enable-url-token(默认 false),token 默认仅从 header(及开启后的 Cookie)读取,不再回退 URL 参数,避免凭证进入访问日志/Referer。

Bug 修复 / 正确性

  • 滑动续期阈值修正:DefaultAuthenticationManager 续期阈值由 timeout*0.8 改为 timeout*0.2(剩余 TTL 不足 20% 才续期),消除"会话度过 20% 后每请求触发存储写"的写放大。
  • ThreadLocal 异步残留防御:AuthenticationInterceptor.preHandle 进入时先 clearContext 兜底清理一次,降低 Servlet 异步/异常场景下线程回池残留导致的"用户串号"风险。
  • JsonUtil 序列化失败显式抛错:不再静默返回空串,改为抛 TinySecurityException,杜绝"登录成功但立即 401"的隐蔽故障。
  • SingleSessionRepository 在线索引并发收敛:list 变更统一由单锁保护,弃用 put 整体替换,修复并发计数丢失更新。
  • login() 成功路径异常隔离:成功事件发布移出 try 块,自定义事件监听器抛异常不再被误判为登录失败(仅 WARN)。
  • getLoginIdAsInt/Long 异常语义统一:loginId 非数字时抛 TinySecurityException(不再直接抛 NumberFormatException 导致 500)。

API 调整

  • JwtUtil 新增 getVerifiedSubject(secret, token)(验签后取 subject);原 getSubject(token) 不验签,标注 @Deprecated 并在 javadoc 中警告;sign 增加 payload 空校验。

工程清理

  • 清理生产类残留 main()/System.out/printStackTrace(BCrypt/SimpleHash/SM3Hash/SM3ConvertUtil/banner 输出);README 版本号同步至 1.3.3 并更新配置说明。

1.3.2

发布日期:2026-08-27 | 升级路径:1.3.1 → 1.3.2 | 完整分析见 docs/project-analysis-2026-08.md

类型概览

维度 内容
新增特性 4 项(enable-cookie 开关、jwt-timeout 配置、Cookie 安全属性配置、登出清理浏览器 Cookie)
Bug 修复 3 项(JWT 公开默认密钥、JWT 过期时间硬编码、非 Web 线程登录 NPE)
安全修复 1 项(日志凭证泄露链路)
行为变更 2 项(未配置 jwt-secret 时改用随机密钥、Cookie 模式默认关闭)

安全修复

  • 移除 JWT 硬编码默认密钥:此前未配置 tiny-security.jwt-secret 时会静默使用一个已在开源文档中公开的内置密钥,且 LoginSubject.toString() 会输出会话凭证(日志泄露)——两者组合存在伪造会话的风险。现在 JwtUtil 对空密钥直接抛出 IllegalArgumentException,不再有任何内置兜底密钥;LoginSubject.toString() 对 credentials 脱敏输出。
  • 非 Web 线程登录 NPE 修复:定时任务 / MQ 消费者等未绑定请求上下文的线程调用 login() 时,CookieUtil.setCookie 不再因 response 为 null 抛出空指针,改为跳过 Cookie 写入并正常返回 token。

Bug 修复

  • JWT 过期时间硬编码 30 天:timeout 配置超过 30 天时会话会在 30 天处静默失效(401)。现新增 jwt-timeout 配置(默认 2592000 秒即 30 天),且实际生效值取 max(jwt-timeout, timeout):默认行为不变,超长会话配置不再提前失效。
  • Cookie 生存期与会话不同步:登录 Cookie 的 maxAge 由硬编码 86400 秒改为与会话 timeout 一致,不再出现「Cookie 比会话活得久」。
  • 登出未清理浏览器 Cookie:logout() / logout(request) 现在会写回 maxAge=0 的同名 Cookie,浏览器侧凭证立即失效。

新增特性

  • Cookie 模式开关(enable-cookie):

    tiny-security:
      enable-cookie: false  # 默认 false;开启后登录写 Cookie、登出清理 Cookie、并允许从 Cookie 读取 token
  • JWT 自身有效期可配置(jwt-timeout):

    tiny-security:
      jwt-timeout: 2592000  # 单位秒,默认30天;实际生效值不低于会话timeout
  • Cookie 安全属性配置:

    tiny-security:
      cookie-secure: false    # 是否仅 HTTPS 传输,默认 false(生产建议开启)
      cookie-same-site: LAX   # SameSite 属性,默认 LAX(可选 STRICT/LAX/NONE,防御 CSRF)
  • 未配置 jwt-secret 时的安全兜底:启动时自动生成 128 位随机密钥并打印 WARN 日志(提示重启后会话失效、生产环境必须配置固定密钥),替代原先静默使用公开默认密钥的行为。

⚠️ 行为变更(升级必读)

  • Cookie 模式默认关闭(enable-cookie,默认 false):此前登录总是写 Cookie、且 token 会自动从 Cookie 中读取;现在默认纯 token 模式(仅 header 与 URL 参数)。前后端不分离、依赖 Cookie 传递 token 的项目升级后必须显式配置 enable-cookie: true,否则登录不再写 Cookie、请求也无法从 Cookie 中取到 token(全部 401)。
  • 未配置 jwt-secret 时改用随机密钥:此前未配置密钥的项目可以跨重启保持会话(因为使用内置固定密钥);升级后每次重启会话全部失效。生产环境请务必配置固定密钥。
  • 直接调用 JwtUtil.sign(null, ...) / JwtUtil.getClaims(null, ...) 的代码将抛出 IllegalArgumentException(原先静默使用内置密钥);JwtUtil.sign 新增带 expireSeconds 参数的重载,原三参重载保持兼容(默认 30 天)。

升级检查清单

  • 依赖 Cookie 传 token 的(前后端不分离)项目:务必配置 enable-cookie: true,否则升级后无法从 Cookie 读取 token
  • 检查是否已配置 tiny-security.jwt-secret(未配置的项目重启后会话失效)
  • 如直接使用 JwtUtil 工具类,确认未依赖「空密钥走内置默认值」的旧行为
  • 生产环境建议开启 cookie-secure: true
  • LoginSubject.toString() 不再输出 credentials,如有依赖该输出的日志排查逻辑需注意

1.3.1版本发布

Choose a tag to compare

@llllllxy llllllxy released this 09 Aug 11:51

tiny-security 1.3.1 升级日志

发布日期:2026-08-09
升级路径:1.3.0 → 1.3.1
适用分支:springboot3(Spring Boot 3.x / JDK 17+) 和 springboot2(Spring Boot 2.x / JDK 8)


一、版本概览

1.3.1 是一个架构重构 + 性能优化 + 安全加固版本。本次更新移除了全局静态单例模式,改为 Spring 原生依赖注入;修复了会话调度线程泄露问题;优化了授权检查的 Redis 访问次数;新增了异常响应状态码控制配置项;同时移除了存在安全隐患的加密工具类。

维度 说明
新增特性 2 项(异常 HTTP 状态码强制 200、授权按需查询优化)
Bug 修复 1 项(会话调度线程泄露)
破坏性变更 3 项(GlobalConfig 移除、AuthProperties 迁移、AESUtil/RSAUtil 删除)
涉及提交 6 次功能性提交 + 1 次版本发布
代码变更 +1,288 / -840 行(含测试)

二、新增特性

2.1 异常响应 HTTP 状态码强制 200(force-http-status-200)

提交: 8199d0c

背景: 部分前端框架(如 axios)对非 2xx 状态码会触发异常拦截,导致业务错误码需要额外处理。新增此配置后,异常响应统一返回 HTTP 200,由响应体 code 字段表达真实业务错误。

配置方式:

tiny-security:
  force-http-status-200: true  # 默认 false

行为说明:

配置值 HTTP 状态码 响应体 code 字段
false(默认) 真实错误码(401/403/409/500) 真实业务错误码
true 统一 200 真实业务错误码(401/403/409/500)

兼容性: 前端判错逻辑无需改动——无论开关如何,响应体 code 字段始终保留真实业务错误码。DefaultExceptionTranslator 保留了无参构造函数,向后兼容。


2.2 授权检查按注解类型按需调用 SPI

提交: d4e9e67

背景: 1.3.0 中,一个接口即使只标注了 @RequiresRoles,授权管理器仍会同时查询角色和权限(两次 Redis 访问);反之亦然。

优化内容: DefaultAuthorizationManager 现根据注解类型按需调用 SPI:

接口注解 1.3.0 行为 1.3.1 行为
仅 @RequiresRoles 查角色 + 查权限 仅查角色
仅 @RequiresPermissions 查角色 + 查权限 仅查权限
同时标注两者 查角色 + 查权限 查角色 + 查权限
PermissionMode.URL 查角色 + 查权限 查角色 + 查权限(URL 模式始终查权限)

收益: 单注解场景下 Redis 访问次数减半。


三、Bug 修复

3.1 会话调度线程泄露修复

提交: 68e6c7b、3756b8e(补充单测)

问题: JDBC 会话仓储(JdbcSessionRepository)和本地缓存(LocalTimeCache)各自创建了 ScheduledExecutorService 调度线程,但在应用停机时没有真正 shutdown。LocalTimeCache.endRefreshThread() 仅将 refreshFlag 标记设为 false,线程本身仍在运行。

影响场景:

  • 应用正常停机时线程未关闭
  • Spring DevTools 热重启导致线程累积
  • 多上下文(如 Spring MVC + WebSocket)场景下线程泄露

修复方案:

类 修复方式
JdbcSessionRepository 实现 DisposableBean,destroy() 中调用 executorService.shutdownNow()
SingleSessionRepository 实现 DisposableBean,destroy() 中调用 timedCache.endRefreshThread()
LocalTimeCache 移除 refreshFlag 标记机制,endRefreshThread() 改为直接 executorService.shutdownNow()

四、破坏性变更(⚠️ 升级必读)

4.1 移除 GlobalConfig / GlobalConfigUtils 全局静态单例

提交: 776dac9

变更说明:

项目 1.3.0 1.3.1
配置持有方式 GlobalConfig 全局静态单例 + GlobalConfigUtils 访问器 Spring 容器依赖注入
初始化时机 ContextRefreshedEvent 事件监听 Bean 构造时注入
AuthAutoConfiguration 实现 ApplicationListener<ContextRefreshedEvent> 移除该接口,改为构造注入

删除的类:

  • org.tinycloud.security.config.GlobalConfig(217 行)
  • org.tinycloud.security.config.GlobalConfigUtils(66 行)

升级影响:

  • 如果你的代码中直接调用了 GlobalConfig.getXxx() 或 GlobalConfigUtils.getGlobalConfig(),需要改为通过 Spring 注入获取对应 Bean。
  • 框架内部所有拦截器、AuthProvider 已改为构造注入,框架自身使用不受影响。

4.2 AuthProperties 包路径迁移

提交: 776dac9

项目 1.3.0 1.3.1
所在模块 tiny-security-boot-starter tiny-security-core
完整路径 org.tinycloud.security.AuthProperties org.tinycloud.security.config.AuthProperties

升级影响:

  • 如果你通过 import 引用了 AuthProperties,需要更新 import 路径。
  • yml 配置前缀 tiny-security 不变,无需修改配置文件。
  • @EnableConfigurationProperties(AuthProperties.class) 注解由 AuthAutoConfiguration 自动处理,用户通常无感知。

4.3 移除 AESUtil 和 RSAUtil 加密工具类

提交: 7cb7eb3

删除的类:

  • org.tinycloud.security.util.secure.AESUtil(196 行)
  • org.tinycloud.security.util.secure.RSAUtil(128 行)

删除原因:

  1. 对称/非对称加密不属于认证框架职责边界
  2. AESUtil 存在硬编码默认密钥安全隐患
  3. RSAUtil 未使用 OAEP 填充,存在安全风险
  4. 框架核心代码从未引用这两个类

保留的算法:

类别 算法 类名 状态
摘要算法 MD5 / SHA-256 / SM3 DigestUtil / SM3Hash ✅ 保留
密码哈希 BCrypt BCrypt ✅ 保留

升级影响: 如果你的业务代码使用了 AESUtil 或 RSAUtil,请迁移至以下替代方案:

  • JDK JCA(javax.crypto.*)
  • Hutool(cn.hutool.crypto.*)
  • BouncyCastle

五、架构改进

5.1 引入 TinySecurityFacade 门面模式

提交: 776dac9

新增 org.tinycloud.security.TinySecurityFacade(180 行),设计参照 Sa-Token 的 StpUtil/StpLogic 模式:

AuthUtil(静态外观,用户调用不变)
    ↓ delegate
TinySecurityFacade(Spring Bean,构造注入依赖)
    ↓
SecurityContextRepository / AuthorizationEvaluator

设计要点:

  • AuthUtil 是静态外观类,用户侧调用方式(AuthUtil.getLoginId() 等)完全不变
  • TinySecurityFacade 是 Spring Bean,通过构造注入获取 SecurityContextRepository
  • 内部依赖可测试、可替换,解决了全局静态单例不可 Mock 的问题

5.2 拦截器改为构造注入

提交: 776dac9

拦截器 1.3.0 依赖获取方式 1.3.1 依赖获取方式
AuthenticationInterceptor 从 GlobalConfig 静态获取 构造注入 AuthenticationManager + SecurityContextRepository
AuthorizationInterceptor 从 GlobalConfig 静态获取 构造注入 AuthorizationManager + SecurityContextRepository + SecurityEventPublisher + AuthProperties

六、升级指南

6.1 Maven 依赖升级

<!-- Spring Boot 3.x -->
<dependency>
    <groupId>top.lxyccc</groupId>
    <artifactId>tiny-security-boot3-starter</artifactId>
    <version>1.3.1</version>
</dependency>

6.2 升级检查清单

按以下顺序检查你的项目:

  • 步骤 1: 全局搜索 GlobalConfig 和 GlobalConfigUtils,如有引用需改为 Spring 注入方式
  • 步骤 2: 全局搜索 org.tinycloud.security.AuthProperties 的 import,更新为 org.tinycloud.security.config.AuthProperties
  • 步骤 3: 全局搜索 AESUtil 和 RSAUtil,如有使用迁移至 JCA / Hutool / BouncyCastle
  • 步骤 4: 如果自定义了 DefaultExceptionTranslator,确认是否需要传入 forceHttpStatus200 参数
  • 步骤 5: 检查是否有代码直接依赖 LocalTimeCache.refreshFlag 字段(已移除)
  • 步骤 6: 验证 AuthUtil 调用方式未变(正常情况下无需改动)

6.3 兼容性说明

用户侧 API 兼容性
AuthUtil.getLoginId() 等静态方法 ✅ 完全兼容,调用方式不变
yml 配置 tiny-security.* ✅ 完全兼容,前缀不变
@RequiresRoles / @RequiresPermissions ✅ 完全兼容
自定义 SessionRepository ✅ 兼容(建议实现 DisposableBean 管理线程)
自定义 ExceptionTranslator ✅ 兼容(DefaultExceptionTranslator 保留无参构造)
直接使用 GlobalConfig ❌ 已移除,需改为注入
直接使用 AESUtil / RSAUtil ❌ 已移除,需迁移

七、提交记录

序号 提交哈希 日期 类型 说明
1 d4e9e67 2026-07-18 feat 授权检查按注解类型按需调用 SPI,减少 Redis 访问
2 68e6c7b 2026-07-18 fix 会话调度线程泄露修复(JdbcSessionRepository / SingleSessionRepository / LocalTimeCache)
3 3756b8e 2026-07-18 test 补充 SessionRepositoryLifecycleTest 生命周期单测
4 8199d0c 2026-08-07 feat 新增 force-http-status-200 异常响应状态码配置项
5 7cb7eb3 2026-08-08 refactor 移除 AESUtil 和 RSAUtil 加密工具类
6 776dac9 2026-08-08 refactor 重构安全框架配置和依赖注入机制(移除 GlobalConfig,引入 TinySecurityFacade)
7 e54d4e8 2026-08-09 release 版本号升级至 1.3.1

八、致谢

感谢所有贡献者和使用者的反馈与支持。如遇升级问题,请提交 Issue。

1.3.0版本发布

Choose a tag to compare

@llllllxy llllllxy released this 08 Jun 13:26

重大更新,部分类包名更改,需要进行适配修改
1、安全架构重构并补齐回归测试
2、重构AuthAutoConfiguration配置类依赖注入方式
3、增加默认异常翻译器,无需再额外配置全局异常处理

1.2.7版本发布

Choose a tag to compare

@llllllxy llllllxy released this 11 Dec 13:40

重大重构,需根据使用文档重新进行适配
1、支持控制同时在线人数max-concurrent-logins属性
2、对于异常的处理进行优化
3、feat: 重构,直接在AuthAutoConfiguration里配置Interceptor,无需自己再进行拦截器的配置,详见文档
4、feat: 增加perm-check-enabled属性,用于配置是否开启权限校验
5、feat: 代码重构,部分属性和类名更加标准化
6、优化部分加密工具类

1.2.4版本发布

Choose a tag to compare

@llllllxy llllllxy released this 30 Jun 03:14

1、feat: 优化getLoginId方法
2、feat: PermissionInfoInterface改为传入LoginSubject
3、feat: 重载出String login(Object loginId, Map<String, Object> extraInfo)方法,以用于在会话中存储额外的扩展信息

1.2.3版本发布

Choose a tag to compare

@llllllxy llllllxy released this 11 Jun 07:17

1、feat: getLoginId方法增加转换方法
2、feat: 如果权限模式为注解,并且类上或方法上没有注解,则直接返回(提升性能,省的每次都调用获取权限角色列表)

1.2.2版本发布

Choose a tag to compare

@llllllxy llllllxy released this 16 May 08:05

1、代码重构,优化了大量的地方
2、token改造为JWT的方式,凭证存在jwt里,这样可以防止伪造token,大大减小存储层的压力
3、AuthProvider新增加一些实用的公共方法
4、toke-style属性更名为为credentials-style
5、新增perm-check-mode配置,默认为annotation,即为注解鉴权,支持以url路径自动对应权限校验权限方式,配置成url即可

1.1.0 版本更新

Choose a tag to compare

@llllllxy llllllxy released this 06 Sep 02:08

1、功能重构,减少刷新次数,大幅度提升效率和性能
2、session表结构重构,提高JdbcAuthProvider的整体性能

1.0.7 版本更新

Choose a tag to compare

@llllllxy llllllxy released this 05 Sep 02:43

1、重构为多moudle项目,更合理了

1.0.6 版本更新

Choose a tag to compare

@llllllxy llllllxy released this 28 Feb 03:56

1、适配springboot3版本