Skip to content

feat(auth): 新增 auth-refresh-token 模块(可轮换的 Refresh Token 登录会话) - #25

Merged
Charles7c merged 3 commits into
devfrom
feat/auth-refresh-token
Oct 4, 2026
Merged

Charles7c merged 3 commits into
devfrom
feat/auth-refresh-token

Conversation

@Charles7c

@Charles7c Charles7c commented Sep 27, 2026 •

Copy link
Copy Markdown
Member

变更类型

  • 新特性(feat)
  • 问题修复(fix)
  • 功能优化(refactor / perf / chore / style)
  • 文档变更(docs)
  • 构建、CI 或依赖升级(build / ci)
  • 测试(test)
  • 其他

破坏性变更

  • 本 PR 包含破坏性变更(BREAKING CHANGE),已在变更目的中说明影响与迁移方式

变更目的

从 continew-admin#229 的 continew-auth-refresh 模块抽取,落地为 starter 认证家族的新成员 continew-starter-auth-refresh-token,配合 continew-admin 4.2.0 发布(admin 侧将在后续 PR 中删除自有模块、切换为依赖本模块)。

为 Web、App 与小程序提供可轮换的 Refresh Token 登录态:缩短 Access Token 生命周期,过期后由 Refresh Token 安全恢复原登录会话,并支持跨端会话统一失效(强退、顶下线、密码修改、租户/客户端禁用)。

解决方案

会话模型(延续 admin#229 已评审设计)

  • sessionId.secret 无状态令牌:服务端只存 secret 的 HMAC-SHA256 指纹并常量时间比对,Redis 泄露不暴露可用令牌
  • 密钥由 HKDF-SHA256(RFC 5869)派生,隔离指纹密钥与快照加密密钥用途;AES-256-GCM 加密快照保证崩溃后可恢复同一组令牌
  • R0→R1 原子轮换由指纹门禁完成,宽限期(默认 30 秒,覆盖弱网与小程序重试窗口)内并发/重复请求幂等返回首次结果
  • 宽限期外的上一代令牌属于明确重放,撤销整个登录会话(OAuth 2.0 Security BCP / RFC 9700 §4.14)
  • 统一撤销收敛于「策略锁 → 会话锁」固定顺序,撤销后经 Redisson RTopic 广播,其它实例子秒级关闭对应 WebSocket 连接
  • Cookie 模式强制 Origin/Referer 白名单校验(含子域通配,通配正则用独占量词避免回溯),SameSite=None 必须配合 Secure
  • 刷新限流默认使用连接对端地址,仅显式配置可信代理后解析 X-Forwarded-For(配置错误 fail-safe)
  • RefreshTokenService.refresh() 固化四步安全契约(resolve → 限流 → 来源校验 → 轮换),避免业务方漏调用导致防护静默失效

抽取边界(本模块零业务实体依赖)

业务方提供 说明
RefreshSessionPrincipal 登录主体快照(用户/昵称/租户/IP/设备),登录时由业务方映射传入
RefreshAccessTokenIssuer 轮换回调中重新签发 Access Token 的适配点,返回 IssuedAccessToken
RefreshClientPolicy 客户端令牌策略(有效期/传输模式/并发数),与业务客户端模型解耦

模块返回统一的 RefreshIssueResult(含轮换幂等回放结果),由业务方映射为实际响应体;登录/刷新 HTTP 端点保留在业务系统侧。

Starter 化改造

  • 配置前缀 continew-starter.refresh-token.*,经 AuthRefreshAutoConfiguration 自动装配,continew-starter.refresh-token.enabled 可整体关闭;装配顺序显式声明 after = RedissonAutoConfiguration(Redis 为硬性依赖,缺失时整体跳过而非启动失败)
  • 多标签页推送能力下沉到 WebSocket 模块:WebSocketSessionDao 新增 listByKey 默认方法、WebSocketUtils 新增 sendMessageToAll,不改动既有 sendMessage 语义;认证模块以多标签页 DAO 接管默认实现,撤销时可全量关闭
  • 未引入 Lombok,全手写 getter/setter,与项目一致;补齐 @author/@since 2.17.0 与 LGPL License Header;模块登记于 auth 聚合器、BOM、PropertiesConstants
  • 新增禁止单行 Javadoc 的 Checkstyle 规则,并补齐 core/encrypt/json 模块存量注释

测试情况

  • 新增模块自带 67 个单元测试(starter 仓库首批单元测试):令牌轮换/重放、宽限期幂等、撤销与失效原因、Cookie 来源校验(含恶意 Origin 拒绝)、密钥隔离(HKDF)、多标签页 WebSocket 撤销、自动配置装配契约(缺 Redisson 时静默跳过)等场景,全部通过
  • ./mvnw -B verify 全仓构建通过:Enforcer / Spotless / Checkstyle(0 violations)/ SpotBugs(0 BugInstance)四道门禁全绿
  • admin 侧集成验证由后续 admin PR 配合 4.2.0 发布完成(本 PR 为纯新增模块,不影响现有使用方)

Changelog

模块 Changelog Related issues
auth-refresh-token 新增可轮换的 Refresh Token 登录会话模块(轮换、重放保护、统一撤销、WebSocket 联动),配合 continew-admin 4.2.0 continew-admin#229
messaging-websocket WebSocket 会话 DAO 支持多标签页:新增 listByKey 与 sendMessageToAll -
checkstyle 新增禁止单行 Javadoc 规则,并补齐存量注释 -

提交前确认

  • 一个 PR 只解决一个 Issue,不夹带无关改动
  • 本地 ./mvnw verify 四道门禁全部通过(被 Spotless 拦截时使用 -Pformat 修复)
  • 已完整填写 Changelog,并关联相关 Issue
  • commit message 符合 Conventional Commits(约定式提交)规范
  • 如包含 AI 生成的较大改动,相关 commit 已添加 Assisted-by: <智能体> 标记
  • 已签署 CLA(首次贡献可在 PR 创建后按机器人提示完成签署)
  • 目标分支正确:dev(新功能与优化)或 x.x.x 维护分支(仅 Bug 修复)

@Charles7c
Charles7c force-pushed the feat/auth-refresh-token branch 11 times, most recently from 8690381 to 82e28d7 Compare October 3, 2026 16:04
- 新增 RegexpSingleline 规则:Javadoc 一律展开为多行,禁止单行写法
- 补齐 core / encrypt / json 模块存量单行 Javadoc
- JavadocMethod 的 allowMissingParamTags、allowMissingReturnTag 暂保持 true,存量约 457 处待专项补齐后再收紧

Assisted-by: WorkBuddy
浏览器多标签页共用同一客户端 ID 时,默认 DAO 以 Key 为唯一维度、后建连接覆盖前者,
既无法按 Key 全量推送,也无法在撤销时全量关闭。

- WebSocketSessionDao 新增 listByKey 默认方法:单连接实现返回至多一条会话,多标签页实现返回全部存活连接
- WebSocketUtils 新增 sendMessageToAll,按客户端 Key 对全部存活连接逐一投递
- 不改动既有 sendMessage 语义,避免对存量使用方的破坏性变更

Assisted-by: WorkBuddy
@Charles7c
Charles7c force-pushed the feat/auth-refresh-token branch from 82e28d7 to 7469c0e Compare October 3, 2026 16:49
从 continew-admin#229 的 continew-auth-refresh 模块抽取,落地为 starter 认证家族新成员,
配合 continew-admin 4.2.0 发布(admin 侧后续 PR 删除自有模块并切换为依赖本模块)。

会话模型:
- sessionId.secret 无状态令牌:服务端只存 secret 的 HMAC-SHA256 指纹并常量时间比对,Redis 泄露不暴露可用令牌
- HKDF-SHA256 分离指纹密钥与快照加密密钥;AES-256-GCM 加密轮换快照,崩溃后可恢复同一组令牌
- R0→R1 原子轮换由指纹门禁完成;宽限期(默认 30 秒,覆盖弱网重试)内并发/重复请求幂等返回首次结果
- 宽限期外的上一代令牌视为明确重放,撤销整个登录会话(OAuth 2.0 Security BCP / RFC 9700 §4.14)
- 统一撤销收敛于「策略锁 → 会话锁」固定顺序,撤销后经 Redisson RTopic 广播关闭对应 WebSocket 连接(多标签页语义)
- Cookie 模式强制 Origin/Referer 白名单校验(含子域通配),SameSite=None 必须配合 Secure
- 刷新限流默认使用连接对端地址,仅显式配置可信代理后解析 X-Forwarded-For(配置错误 fail-safe)
- RefreshTokenService.refresh() 固化四步安全契约(resolve → 限流 → 来源校验 → 轮换),避免业务方漏调用导致防护静默失效

抽取边界(零业务实体依赖):业务方提供 RefreshSessionPrincipal、RefreshAccessTokenIssuer、RefreshClientPolicy。

其它:
- 新增 67 个单元测试(starter 仓库首批),并显式固定 maven-surefire-plugin 版本
- 模块登记于 auth 聚合器、BOM、PropertiesConstants(continew-starter.refresh-token.*)

Assisted-by: WorkBuddy
@Charles7c
Charles7c force-pushed the feat/auth-refresh-token branch from 7469c0e to 3fafa77 Compare October 4, 2026 01:59
@sonarqubecloud

sonarqubecloud Bot commented Oct 4, 2026

Copy link
Copy Markdown

@Charles7c
Charles7c merged commit ac5a752 into dev Oct 4, 2026
7 of 8 checks passed
@Charles7c
Charles7c deleted the feat/auth-refresh-token branch October 4, 2026 10:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant