拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Bytebase 令牌时长设置设计与实现:访问令牌与刷新令牌的分治治理

Bytebase 令牌时长设置设计与实现访问令牌与刷新令牌的分治治理【免费下载链接】bytebaseDatabase governance built for humans and agents — controlling changes and access across every major database.项目地址: https://gitcode.com/GitHub_Trending/by/bytebase导读本文围绕 Bytebase 工作区设置中的令牌时长Token Duration配置能力展开完整剖析访问令牌Access Token与刷新令牌Refresh Token时长分离配置这一功能从设计到落地的全过程。读者将掌握为什么旧的token_duration设置需要重构、两个新配置字段在 Proto 层如何定义、存量数据如何无损迁移、后端如何按特性开关决定令牌有效期以及前端设置界面如何联动生效。全文以 设计文档 与 实现计划 为主体结合当前仓库中的 Proto、迁移脚本、Go 源码与前端代码逐一印证。一、背景legacytoken_duration的历史包袱Bytebase 早期只支持一种访问令牌但它实际上表现得像刷新令牌——默认有效期长达 7 天。这在当时简化了认证模型却带来了两个问题命名与语义错位名为access token的令牌其实承担了刷新令牌的长生命周期职责安全语义混乱无法分级控制工作区无法独立配置短期访问凭证与长期会话续期凭证的时长要么全部很短频繁重新登录要么全部很长安全风险面大。设计文档明确指出现有的token_duration设置项与FEATURE_SIGN_IN_FREQUENCY_CONTROL特性开关正是这一历史时期的遗留命名见 设计文档。本次改动将令牌类型彻底分离并为每一类令牌提供独立的、可配置的有效期令牌类型语义默认有效期Access Token短生命周期访问凭证到期后需刷新1 小时Refresh Token长生命周期会话续期凭证7 天二、设计核心一次改名 新增的 Proto 演进整个方案在协议层只做两件事把旧的token_duration重命名为refresh_token_duration沿用原字段号 4保证 wire 兼容并新增access_token_duration字段字段号 18。2.1 Store Proto 变更存储层定义位于 proto/store/store/setting.protoWorkspaceProfileSetting消息中的最终实现如下// The duration for refresh token. Default is 7 days. google.protobuf.Duration refresh_token_duration 4; // ... // The duration for access token. Default is 1 hour. google.protobuf.Duration access_token_duration 18;对应源码位置见 setting.proto 与 setting.proto。字段类型使用google.protobuf.Duration由google/protobuf/duration.proto引入见 setting.proto。2.2 V1 API Proto 变更面向 API 的WorkspaceProfileSetting消息位于 proto/v1/v1/setting_service.proto与 Store 层保持同样的字段定义refresh_token_duration 4第 229 行、access_token_duration 18第 286 行。2.3 字段号选择的技术考量沿用字段号 4token_duration原本就是字段号 4重命名不改号老客户端按字段号解析仍能读到刷新令牌时长属于无损的 schema 演进新字段用 18WorkspaceProfileSetting在长期迭代中字段号 517 已被占用公告、最大请求有效期、域名、密码限制等详见 setting.proto因此新字段选在 18并保留 16 号字段作为预留reserved 16。三、存量数据迁移JSONB 键名无损改写工作区设置以 JSON 形式存储在 PostgreSQL 的setting表中历史数据里的键名是tokenDuration。迁移脚本 0013##rename_token_duration_setting.sql 通过jsonb_set将旧键改名为新键-- Rename tokenDuration to refreshTokenDuration in WORKSPACE_PROFILE setting UPDATE setting SET value jsonb_set( value - tokenDuration, {refreshTokenDuration}, value-tokenDuration ) WHERE name WORKSPACE_PROFILE AND value ? tokenDuration;迁移要点条件value ? tokenDuration保证只处理仍带旧键的行幂等安全value - tokenDuration先移除旧键jsonb_set再写入新键值原样保留迁移目录为backend/migrator/migration/3.14/说明该功能随 3.14 版本发布。四、后端实现从默认常量到特性门控4.1 默认时长常量backend/api/auth/auth.go 中定义了两类令牌的默认时长const ( // DefaultAccessTokenDuration is the default access token expiration duration. DefaultAccessTokenDuration 1 * time.Hour // DefaultRefreshTokenDuration is the default refresh token expiration duration. DefaultRefreshTokenDuration 7 * 24 * time.Hour )4.2 时长解析函数GetAccessTokenDuration/GetRefreshTokenDurationbackend/api/auth/header.go 实现了两个核心函数逻辑骨架一致先取默认值 → 校验特性开关 → 读取工作区设置 → 有配置则覆盖默认值。以GetAccessTokenDuration为例func GetAccessTokenDuration(ctx context.Context, store *store.Store, licenseService *enterprise.LicenseService, workspaceID string) time.Duration { accessTokenDuration : DefaultAccessTokenDuration // If the sign-in frequency control feature is not enabled, return default duration if err : licenseService.IsFeatureEnabled(ctx, workspaceID, v1pb.PlanFeature_FEATURE_TOKEN_DURATION_CONTROL); err ! nil { return accessTokenDuration } workspaceProfile, err : store.GetWorkspaceProfileSetting(ctx, workspaceID) if err ! nil { return accessTokenDuration } if workspaceProfile.GetAccessTokenDuration().GetSeconds() 0 { accessTokenDuration workspaceProfile.GetAccessTokenDuration().AsDuration() } return accessTokenDuration }GetRefreshTokenDuration在相同结构之外还叠加了密码轮换password rotation约束当工作区配置了PasswordRestriction.PasswordRotation且其时长小于刷新令牌时长时取两者中的较小值强制刷新令牌提前失效从而把必须定期改密的策略落实到会话层面。该逻辑的注释说明见 header.go。4.3 实现与设计文档的差异以当前仓库为准设计文档与最终实现存在几处细微差异阅读时应以仓库现状为准特性开关改名设计文档写的是FEATURE_SIGN_IN_FREQUENCY_CONTROL当前代码实际使用的是FEATURE_TOKEN_DURATION_CONTROL见 header.go。从源码结构看FEATURE_SIGN_IN_FREQUENCY_CONTROL属于旧命名体系实现阶段同步做了改名函数签名最终实现的两个函数均增加了workspaceID string参数header.go用于多工作区SaaS场景下的隔离读取密码轮换联动最终实现额外引入了FEATURE_PASSWORD_RESTRICTIONS门控下的密码轮换取小逻辑这在设计文档的Constraints章节中未展开属于实现阶段的增强。4.4 调用链登录、刷新与会话续期backend/api/v1/auth_service.go 中时长解析函数被接入四个关键节点调用点行号用途Refresh方法L618刷新会话时签发新的访问令牌generateLoginToken相关L827登录成功后生成访问令牌issueSessionCookies路径L1086计算会话过期时间会话续期逻辑L1119计算刷新令牌有效期典型调用形如accessTokenDuration : auth.GetAccessTokenDuration(ctx, s.store, s.licenseService, workspaceID) accessToken, err : auth.GenerateAccessToken(user.Email, workspaceID, s.secret, accessTokenDuration)4.5 Cookie 生命周期的配套调整GetTokenCookie 中访问令牌 Cookie 的过期时间改为与刷新令牌时长对齐而非访问令牌时长。注释解释了原因Refresh()需要能从过期的 JWT 中提取工作区信息即使空闲很久也能续期API 中间件会拒绝过期的 JWT因此一个过期的 Cookie 无害见 header.go。这保证了短访问令牌 长会话模型下用户体验的连续性。五、前端实现设置界面的双字段编排5.1 类型层默认值frontend/src/types/setting.ts 中定义了与后端一致的默认值export const defaultAccessTokenDurationInHours 1; export const defaultRefreshTokenDurationInHours 7 * 24;5.2 设置组件的本地状态设置组件SignInFrequencySetting对应 AccountSection.tsx 中的设置区域的本地状态拆分为interface LocalState { accessTokenDuration: number; accessTokenTimeFormat: MINUTES | HOURS; refreshTokenDuration: number; refreshTokenTimeFormat: HOURS | DAYS; inactiveTimeout: number; showFeatureModal: boolean; }getInitialState按秒数大小自动选择展示单位访问令牌时长小于 1 小时按分钟展示、否则按小时展示刷新令牌时长小于 1 天按小时展示、否则按天展示。5.3 保存与单位换算保存逻辑通过updateWorkspaceProfile配合updateMask精确更新单个字段避免全量覆盖const handleAccessTokenDurationChange async () { const seconds state.accessTokenTimeFormat MINUTES ? state.accessTokenDuration * 60 : state.accessTokenDuration * 60 * 60; await settingV1Store.updateWorkspaceProfile({ payload: { accessTokenDuration: create(DurationSchema, { seconds: BigInt(seconds), nanos: 0, }), }, updateMask: create(FieldMaskSchema, { paths: [value.workspace_profile.access_token_duration], }), }); };刷新令牌同理但换算因子为HOURS → 60 * 60、DAYS → 24 * 60 * 60updateMask 路径为value.workspace_profile.refresh_token_duration。5.4 单位切换的取值约束为避免切换单位时数值溢出语义范围组件对输入做了 watch 约束切换到分钟时访问令牌上限 59切换到小时时刷新令牌上限 23。5.5 国际化文案五个语言文件同步更新了access-token-duration与refresh-token-duration两组文案en-US.json、zh-CN.json、ja-JP.json、es-ES.json、vi-VN.json。中英文案明确了两者的安全语义差异访问令牌访问令牌在需要刷新前保持有效的时间。较短的有效期可提高安全性。刷新令牌用户需要完全重新认证的频率。配置更新后需要用户重新登录才能生效。六、默认值与约束总结令牌类型默认有效期前端可配置单位Access Token1 小时分钟≤59、小时≤23Refresh Token7 天小时≤23、天无上限设计约束设计文档不做时长合法性校验管理员对时长拥有完全控制权系统不强制限制取值范围前端仅为 UX 提供单位级上限约束特性门控该功能由企业版特性FEATURE_SIGN_IN_FREQUENCY_CONTROL实现中更名为FEATURE_TOKEN_DURATION_CONTROL控制未启用时两个函数直接返回默认时长。七、从设计到落地的完整实施流水线结合 实现计划完整变更流水线为Store Proto修改 proto/store/store/setting.proto重命名token_duration→refresh_token_duration新增access_token_durationV1 Proto同步修改 proto/v1/v1/setting_service.proto生成代码buf format -w proto后执行cd proto buf generate数据迁移新增backend/migrator/migration/3.14/下的 JSONB 键名改写 SQL后端常量与函数修改 auth.go 默认常量在 header.go 中实现两个时长解析函数后端调用点更新 auth_service.go 的登录、刷新与会话续期逻辑前端类型更新 setting.ts 默认常量前端组件与文案更新设置组件本地状态、保存逻辑、单位换算与五个 locale 文件构建与检查gofmt格式化 Go 代码、golangci-lint run --allow-parallel-runners、pnpm --dir frontend biome:check与pnpm --dir frontend type-check。八、延伸阅读与验证入口设计原文2025-12-26-token-duration-settings-design.md逐任务实施计划2025-12-26-token-duration-settings.md令牌签发与校验核心backend/api/auth/auth.go时长解析与 Cookie 生命周期backend/api/auth/header.go登录/刷新服务backend/api/v1/auth_service.go数据迁移脚本0013##rename_token_duration_setting.sql前端默认时长frontend/src/types/setting.ts这套短访问令牌 长刷新令牌 企业版特性门控 密码轮换联动的模型既收窄了访问凭证被盗用的攻击面又通过刷新令牌与密码轮换的取小逻辑维持了会话安全的整体一致是 Bytebase 登录频率治理体系中的关键一环。【免费下载链接】bytebaseDatabase governance built for humans and agents — controlling changes and access across every major database.项目地址: https://gitcode.com/GitHub_Trending/by/bytebase创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门