恒美微站
首页
关于我们
建站服务
主题模板
案例展示
资讯中心
联系我们
Backstage 新认证服务迁移指南:从旧版 identity/tokenManager 到 auth/httpAuth
首页
资讯中心
/
Backstage 新认证服务迁移指南:从旧版 identity/tokenManager 到 auth/httpAuth
Backstage 新认证服务迁移指南:从旧版 identity/tokenManager 到 auth/httpAuth
发布时间:2026/9/13 16:07:12
Backstage 新认证服务迁移指南从旧版 identity/tokenManager 到 auth/httpAuth【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage本文基于 Backstage 仓库中的 auth-service-migration.md 编写系统讲解自 1.24 版本起重构后的新认证auth服务。文章覆盖两部分内容一是后端Backend实例层面如何应对默认认证策略default auth policy带来的破坏性变更二是插件与模块Plugin Module层面如何从旧的identity/tokenManager服务迁移到新的auth/httpAuth服务并给出了可直接套用的代码示例与配置片段。读完本文你将掌握新认证架构的核心概念、本地开发的 guest 登录配置以及三个最常见的服务调用迁移范式。背景1.24 起认证服务重构Backstage 后端系统new backend system的认证服务在 1.24 版本中进行了重新设计。除了一组新服务之外最核心的变更在于新后端系统中运行的所有插件默认都会拦截所有未经用户或服务认证的请求这一行为被称为默认认证策略default auth policy。这是本次更新引入的唯一具有破坏性的生产变更它同时影响现有后端实例的部署与本地开发所有插件的请求处理行为未迁移的插件可能出现原本允许匿名访问的端点被默认策略拦截的情况。新认证服务的引入还取代了此前 contrib 目录下的 authenticate-api-requests.md 指南该文件位于仓库的 contrib 目录中。如果你的后端此前安装了该指南所描述的实现应当移除并改用新认证服务。一、后端实例迁移使用新认证服务的前提是后端已经运行在新后端系统之上。如果仍在使用旧系统需要先按照迁移到新后端系统的指南完成升级。1.1 选择保留默认认证策略 or 关闭它升级到最新版本时你可以选择两条路径路径行为适用场景保留默认认证策略所有请求必须携带用户或服务凭据否则被拦截生产环境推荐安全性最佳关闭默认认证策略允许无凭据请求进入插件暂未完成迁移的过渡期未来版本将移除该选项如果你选择保留默认策略需要确保请求包括本地开发时的请求都经过认证如果你此前安装了 contrib 中的 authenticate-api-requests 实现但暂时不想移除也可以先关闭默认策略再平滑过渡。1.2 关闭默认认证策略过渡方案在 app-config 中设置以下配置即可关闭默认认证策略backend: auth: dangerouslyDisableDefaultAuthPolicy: true注意该功能将在未来版本中移除。关闭后请求即使不带任何凭据也能进入后端插件但请求仍会被视为未认证并非所有插件端点都能接受这种请求。若想了解该配置的完整影响可阅读auth 服务文档中的Configuring the service一节——文档同时强调如果启用了权限系统permissions未认证请求会被原样交给权限策略决定允许哪些权限这一点同样适用于插件之间的服务调用除非你为服务调用配置了凭据。务必不要在生产环境关闭默认认证策略除非确实必要并尽快迁移到新认证服务否则你需要自行维护签发 token 的服务。1.3 保留默认策略本地开发启用 guest 登录保留默认策略后本地开发也需要认证。若你此前依赖guest访客身份进行本地开发推荐安装新的 guest provider 模块yarn --cwd packages/backend add backstage/plugin-auth-backend-module-guest-provider然后将其注册到后端入口文件packages/backend/src/index.tsbackend.add(import(backstage/plugin-auth-backend-module-guest-provider));最后在开发配置中加入 guest providerauth: providers: guest: {}guest provider 只应服务于本地开发不要在生产使用。它默认会拒绝在生产环境启用但最好完全避免。如果你没有独立的开发配置文件请在生产配置中显式禁用auth: providers: guest: null如果确实需要在非开发环境启用 guest 登录可以这样配置有安全风险谨慎使用auth: providers: guest: dangerouslyAllowOutsideDevelopment: true完成上述三步后guest 认证即可工作backstage/core-components中的默认SignInPage会自动检测并启用 guest provider。从源码结构看该模块的实现位于 plugins/auth-backend-module-guest-provider/src/module.ts它通过createBackendModule注册auth插件的guest-provider模块使用createProxyAuthProviderFactory组合guestAuthenticator与signInAsGuestUser解析器并从auth.providers.guest配置读取设置例如dangerouslyAllowOutsideDevelopment由此可确认文档中guest provider 会读取该配置节的行为确实由signInAsGuestUser(config.getConfig(auth.providers.guest))支撑。1.4 自定义 identity / tokenManager 的适配由于默认认证策略对运行在新后端系统中的所有插件统一生效你不必逐个检查插件是否受保护。尚未迁移的插件可能暴露的隐患是某些本应允许匿名访问的端点现在会被默认策略拦截。若想为某个插件临时放行可以为该插件安装一个模块通过 http router 服务 添加所需策略具体写法见下文插件与模块迁移部分。如果你有自定义的 identity 或 token manager 服务实现可以使用backstage/backend-common中的createLegacyAuthAdapters辅助函数将它们适配到新认证服务上该函数同样用于插件内部的兼容层详见下文。二、插件与模块迁移插件/模块的迁移分为两个步骤优先级不同步骤内容紧迫程度第一步为新后端系统添加所需的认证策略auth policy更紧急否则插件可能在新后端系统中无法正常工作第二步迁移到新的 auth 服务不太紧急直到旧认证服务被移除前都非必须2.1 添加认证策略Auth Policy如果插件支持新后端系统且需要接受未认证请求或仅凭用户 cookie 认证的请求就必须通过httpRouter服务添加例外策略。例如允许/health端点接受未认证请求export default createBackendPlugin({ pluginId: example, register(env) { env.registerInit({ deps: { config: coreServices.rootConfig, logger: coreServices.logger, httpRouter: coreServices.httpRouter, auth: coreServices.auth, httpAuth: coreServices.httpAuth, }, async init({ config, logger, httpRouter, auth, httpAuth }) { httpRouter.use(await createRouter({ config, logger, auth, httpAuth })); // 新增为 /health 端点添加未认证放行策略 httpRouter.addAuthPolicy({ path: /health, allow: unauthenticated, }); }, }); }, });addAuthPolicy是httpRouter服务暴露的 API定义于 packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts它允许你按路径声明允许的认证级别框架会在你的后端代码执行前依据这些策略完成对入站 token 的预先校验。完整的策略类型与用法可参考 http router 服务文档。2.2 使用新 auth 服务本步骤的目标是彻底移除插件内部对旧identity与tokenManager服务的使用改用新的 auth 与 http auth 服务。两点说明插件仍然可以把identity/tokenManager作为可选依赖保留在插件环境中以免破坏现有用户的配置如果你的插件本就不依赖这两个服务也不在内部使用DefaultIdentityClient则本步骤无需执行。下文假设插件以createRouter模式作为对外 API旧后端系统的典型写法。如果你有其它外部 API 面处理方式相同只需相应调整示例。2.2.1 更新新后端系统中的依赖声明第一步在createBackendPlugin的依赖中把identity/tokenManager替换为auth/httpAuth。注意discovery服务必须保留或新增——它是后续兼容层所必需的export default createBackendPlugin({ pluginId: example, register(env) { env.registerInit({ deps: { config: coreServices.rootConfig, logger: coreServices.logger, discovery: coreServices.discovery, httpRouter: coreServices.httpRouter, // 移除 // identity: coreServices.identity, // tokenManager: coreServices.tokenManager, // 新增 auth: coreServices.auth, httpAuth: coreServices.httpAuth, }, async init({ config, logger, discovery, httpRouter, // auth, // httpAuth, }) { const router await createRouter({ config, logger, discovery, auth, httpAuth, }); httpRouter.use(); }, }); }, });如果插件此前不依赖identity/tokenManager直接忽略即可但如果此前不依赖discovery则必须把它加为必需依赖。2.2.2 在createRouter中暴露新 auth 服务为了让新 auth 服务以向后兼容的方式进入插件实现使用backstage/backend-common的createLegacyAuthAdapters辅助函数。它的行为是若提供了新服务实现新后端系统的场景直接透传若未提供新服务则基于旧服务创建回退实现旧服务也没有时再回退到旧服务的默认实现。实际改造createRouter的写法export interface RouterOptions { config: RootConfigService; logger: LoggerService; discovery: DiscoveryService; identity?: IdentityService; // 新增可选参数 auth?: AuthService; httpAuth?: HttpAuthService; } export function createRouter(options: RouterOptions) { // 关键构造 auth / httpAuth const { auth, httpAuth } createLegacyAuthAdapters(options); // ... 其余实现 }两条约束必须遵守如果createRouter原本不接收identity/tokenManager参数不要为了适配而新增它们如果插件为这两个服务提供了任何默认实现必须将其传给createLegacyAuthAdapters。这两条约束共同保证插件行为与迁移前完全一致。如果最终实现只需要auth或httpAuth其中之一记得把用不到的那个从 RouterOptions 中移除。2.2.3 替换旧认证服务调用auth/httpAuth就绪后剩下就是逐处替换identity/tokenManager的调用。以下是三个最常见的迁移范式。范式一发起独立的服务到服务请求旧写法获取一个服务 tokenconst { token } await tokenManager.getToken();新写法const { token } await auth.getPluginRequestToken({ onBehalfOf: await auth.getOwnServiceCredentials(), targetPluginId: plugin-id, // 例如 catalog });onBehalfOf指定以谁的名义发起请求这里用的是插件自身凭据getOwnServiceCredentials适合插件作为调用发起者的场景如周期性批处理索引任务targetPluginId是新引入的必填项它实现了对服务到服务认证更细粒度的控制生成 token 时必须指明请求目标是哪个插件。新方案要求随取随用不可复用永远不要在请求前预先存储并复用 token而应在真正发起请求的瞬间调用getPluginRequestToken否则过期 token 会引发权限问题该注意点同样记录在 auth 服务文档 中。范式二转发来自入站请求的凭据旧写法——直接取出原始 token 并透传给上游router.get(/example/:entityRef, async (req, _res) { const token getBearerTokenFromAuthorizationHeader( req.header(authorization), ); // 用 token 调用下游例如 catalog client const entity await catalogClient.getEntityByRef(req.params.entityRef, { token, }); // 或者把 token 转发给权限评估 await permissions.authorize( [{ permission: examplePermission, resourceRef: entityRef }], { token }, ); });新写法——新服务刻意增加了一步先从入站请求提取凭据再基于凭据为上游请求生成新 token从而避免用户 token 与服务 token 在链路中被直接透传router.get(/example/:entityRef, async (req, _res) { const credentials await httpAuth.credentials(req); // catalog client 目前只接受 token未来会支持直接传凭据 // 因此这里需要基于凭据签发一个新 token const { token } await auth.getPluginRequestToken({ onBehalfOf: credentials, targetPluginId: catalog, }); const entity await catalogClient.getEntityByRef(req.params.entityRef, { token, }); // permissions 服务可以直接接收凭据 await permissions.authorize( [{ permission: examplePermission, resourceRef: entityRef }], { credentials }, ); });注意要让上面permissions的调用成立插件需要改为依赖backstage/backend-plugin-api中的PermissionsService而不是PermissionEvaluator。通用原则重构插件时应尽量让BackstageCredentials对象在内部尽可能远地传递仅在真正使用 token 前一刻才生成 token。httpAuth.credentials用于从请求中提取已验证的凭据其第二参数可选用于限定接受的凭据类型默认同时接受 service 与 user但不含 limited access。更多细节见 http auth 服务文档——该文档同时强调不要仅仅为了确认入站 token 有效而调用httpAuth.credentials框架会在你的代码执行前完成 token 有效性校验只有当你确实需要基于凭据采取动作时才调用它。范式三从请求中获取用户身份旧写法——通过identity服务router.get(/example/by-user, async (req, _res) { const user await identity.getIdentity({ request: req }); if (!user) { throw new AuthenticationError(); } console.log(User ${user.identity.userEntityRef} is making a request); });新写法router.get(/example/by-user, async (req, _res) { const credentials await httpAuth.credentials(req, { allow: [user] }); console.log( User ${credentials.principal.userEntityRef} is making a request, ); });allow: [user]用于把可接受的凭据收窄为用户凭据如果入站请求不是用户认证credentials调用会抛出错误如果业务逻辑并不强制要求用户已认证仅在有用户时使用可以传allow: [user, service, none]然后检查credentials.principal.type再决定如何处理auth服务还提供了auth.isPrincipal(credentials, user)这类辅助方法用于在拿到凭据后进一步判断调用方类型并窄化 TypeScript 类型详见 auth 服务文档。三、迁移检查清单按以下顺序完成迁移可最大限度降低破坏性确认后端运行在新后端系统否则先迁移后端系统本身升级所有插件到最新版本以包含对新 auth 服务的适配决定默认认证策略的去留保留 → 为本地开发配置 guest provider仅开发环境关闭 → 设置backend.auth.dangerouslyDisableDefaultAuthPolicy: true并尽快规划移除检查内部插件/模块需要放行匿名/cookie 请求的端点 → 用httpRouter.addAuthPolicy添加策略使用identity/tokenManager的地方 → 用createLegacyAuthAdapters引入auth/httpAuth并依次替换三类调用独立服务调用、凭据转发、用户身份提取验证本地开发用 guest 登录确认受保护端点行为符合预期对放行端点如/health验证匿名访问可用。延伸阅读Auth 服务文档token 的生成、校验与凭据检查Http Auth 服务文档Express 请求/响应上的凭据收发Http Router 服务文档路由注册与认证策略控制服务到服务认证HTTP 请求链路中 token 的正确使用方式新后端系统总览 与迁移指南Guest provider 模块源码plugins/auth-backend-module-guest-provider/src/module.tshttpRouter服务接口定义packages/backend-plugin-api/src/services/definitions/HttpRouterService.ts【免费下载链接】backstageBackstage is an open framework for building developer portals项目地址: https://gitcode.com/GitHub_Trending/ba/backstage创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考