- 后端
【免费下载链接】angularfire
Angular + Firebase = ❤️
App Check(应用检查)是 Firebase 提供的客户端身份验证机制,用于防止未经授权的客户端访问你的后端资源。本文以 AngularFire 官方文档 docs/app-check.md 为主体,讲解如何在 Angular 应用中通过依赖注入接入 App Check、使用 reCAPTCHA v3 Provider 完成配置,并结合 src/app-check 模块源码剖析其底层实现(调试 Token、Zone 包装、实例管理与 RxJS 集成)。读完本文,你将掌握从ng add @angular/fire到在组件中注入AppCheck的完整实战路径,并理解这些 API 在 Angular 运行时中的行为细节。
App Check 能解决什么问题
按照官方文档的定义,App Check 帮助保护你的 API 资源免受滥用:它通过验证发起请求的客户端是否为可信来源,阻止未经授权的客户端访问你的后端资源。它既可以配合 Firebase 服务使用,也可以配合 Google Cloud 服务使用,甚至可以直接保护你自己实现的后端 API。
简单来说,App Check 的定位是"证明调用方是一个真实、未被篡改的 App",而不是"证明某个用户是登录用户"——它与 Authentication 是互补的两道防线。文档中给出的集成方式是使用reCAPTCHA v3(ReCaptchaV3Provider)作为证明提供方:浏览器端向 Google 的 reCAPTCHA 服务证明自身可信,Firebase 据此签发 App Check Token,后端服务校验该 Token 后才放行请求。
前置条件:安装并初始化 AngularFire
在接入 App Check 之前,需要确保 AngularFire 已经加入你的项目。官方文档给出的命令是:
ng add @angular/fire该命令会完成以下工作(详见 docs/install-and-setup.md):
- 提示你选择要启用的功能模块并选择 Firebase 项目(必要时引导你登录 Firebase)。
- 在应用的
app.config.ts中写入provideFirebaseApp(...)以及你所选功能的 Provider,并将 Firebase 配置内联进去。
因此,在配置 App Check 时,你的app.config.ts中通常已经存在provideFirebaseApp(() => initializeApp({ ... })),App Check 的 Provider 需要挂在同一个配置数组中。
依赖注入:在 app.config.ts 中提供 App Check 实例
这是官方文档的核心步骤。在应用的app.config.ts中,通过provideAppCheck配合 Firebase 的initializeAppCheck函数创建并注册 App Check 实例:
import { ApplicationConfig } from '@angular/core'; import { provideFirebaseApp, initializeApp, getApp } from '@angular/fire/app'; import { provideAppCheck, initializeAppCheck, ReCaptchaV3Provider } from '@angular/fire/app-check'; export const appConfig: ApplicationConfig = { providers: [ provideFirebaseApp(() => initializeApp({ ... })), provideAppCheck(() => initializeAppCheck(getApp(), { provider: new ReCaptchaV3Provider(/* configuration */), })), ... ], ... }几个值得注意的细节:
getApp()而不是新建 App:initializeAppCheck的第一个参数是FirebaseApp实例。这里使用getApp()获取provideFirebaseApp已初始化好的默认 App,保证 App Check 与其它 Firebase 服务共享同一个 App 上下文。- Provider 是可替换的:示例中使用的是
ReCaptchaV3Provider,你需要在 Firebase 控制台为 Web 应用启用 App Check 并获取对应的 site key 填入配置。由于 src/app-check/firebase.ts 会export * from 'firebase/app-check'重新导出整个 Firebase App Check 模块,其它 Provider(如 reCAPTCHA Enterprise 对应的ReCaptchaEnterpriseProvider)同样可以通过@angular/fire/app-check导入使用。 - 配置位置:
provideAppCheck返回的是 Angular 的EnvironmentProviders,与provideFirebaseApp一样必须放在ApplicationConfig.providers数组中。
在组件中注入 AppCheck
配置完成后,即可通过 Angular 依赖注入在组件中使用它。官方文档给出的示例:
import { Component, inject} from '@angular/core'; import { AppCheck } from '@angular/fire/app-check'; @Component({ ... }) export class AppCheckComponent { private appCheck = inject(AppCheck); ... }这里的AppCheck是 AngularFire 提供的注入令牌(InjectToken),其源码定义在 src/app-check/app-check.ts:
export interface AppCheck extends FirebaseAppCheck {} export class AppCheck { constructor(appCheck: FirebaseAppCheck) { return appCheck; } }从源码结构看,AppCheck是一个对底层 FirebaseAppCheck实例的轻量包装:interface AppCheck extends FirebaseAppCheck声明它具备 Firebase App Check 的全部 API,而构造函数直接返回传入的底层实例,使注入到组件中的对象就是那个真实可用的 Firebase 实例本身。
Firebase API 兼容层:从 firebase/app-check 切换到 @angular/fire/app-check
文档明确指出:AngularFire 包装了 Firebase JS SDK,在保证 Angular 中正常运行的同时,提供与官方完全一致的 API。使用方式是把导入路径从firebase/app-check换成@angular/fire/app-check,然后遵循 Firebase 官方文档使用即可。
来看 src/app-check/firebase.ts 的实现,理解"包装"究竟做了什么:
export * from 'firebase/app-check'; import { ɵzoneWrap } from '@angular/fire'; import { getLimitedUseToken as _getLimitedUseToken, getToken as _getToken, initializeAppCheck as _initializeAppCheck, onTokenChanged as _onTokenChanged, setTokenAutoRefreshEnabled as _setTokenAutoRefreshEnabled } from 'firebase/app-check'; export const getLimitedUseToken = ɵzoneWrap(_getLimitedUseToken, true, 2); export const getToken = ɵzoneWrap(_getToken, true); export const initializeAppCheck = ɵzoneWrap(_initializeAppCheck, true); export const onTokenChanged = ɵzoneWrap(_onTokenChanged, true); export const setTokenAutoRefreshEnabled = ɵzoneWrap(_setTokenAutoRefreshEnabled, true);这里有两个关键点:
- 完整导出:
export * from 'firebase/app-check'意味着 Firebase App Check 模块中的所有类型、常量与 Provider 类(如ReCaptchaV3Provider、Token 相关类型等)都原样可用。 - Zone 包装:
initializeAppCheck、getToken、getLimitedUseToken、onTokenChanged、setTokenAutoRefreshEnabled这五个核心函数被ɵzoneWrap包裹。Angular 依靠 Zone.js 触发变更检测,而 Firebase SDK 的回调往往在 Zone 之外执行;经过ɵzoneWrap后,这些函数发起的异步回调会被重新调度回 Angular Zone 内,确保 Token 刷新、状态变化等事件能正确触发视图更新。这是 AngularFire 各模块共用的底层机制。
因此,你可以放心地像使用原生 Firebase 一样调用getToken(appCheck)、onTokenChanged(appCheck, listener)等 API,无需关心 Zone 调度的细节,同时享受与官方文档(reCAPTCHA Provider 的 Getting Started、API Reference)完全一致的用法。
源码级细节:provideAppCheck 的运行时行为
provideAppCheck的实现位于 src/app-check/app-check.module.ts,阅读它可以帮助你理解 App Check 在 Angular 运行时中的完整生命周期。
调试 Token 的自动启用
const LOCALHOSTS = ['localhost', '0.0.0.0', '127.0.0.1']; const isLocalhost = typeof window !== 'undefined' && LOCALHOSTS.includes(window.location.hostname); export function appCheckInstanceFactory(fn: (injector: Injector) => FirebaseAppCheck) { return (zone: NgZone, injector: Injector, platformId: unknown) => { // Node should use admin token provider, browser devmode and localhost should use debug token if (!isPlatformServer(platformId) && (isDevMode() || isLocalhost)) { globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN ??= true; } const appCheck = zone.runOutsideAngular(() => fn(injector)); return new AppCheck(appCheck); }; }从源码可以提炼出三条运行时规则:
- 本地开发自动使用调试 Token:只要满足"非服务端渲染 +
isDevMode()(开发模式)或访问localhost/0.0.0.0/127.0.0.1"任一条件,AngularFire 就会自动设置globalThis.FIREBASE_APPCHECK_DEBUG_TOKEN = true。这会让 Firebase 在本地开发时使用调试 Token 绕过 reCAPTCHA 验证,避免在开发环境中反复触发人机校验。 - 服务端(Node / SSR)走 Admin Token:源码注释明确说明 "Node should use admin token provider",即在服务端渲染场景下不会启用调试 Token,而应由你的服务端环境通过 Firebase Admin SDK 等方式提供 Token。
- 实例在 Zone 外创建:
zone.runOutsideAngular(() => fn(injector))表明 App Check 实例的创建被安排在 Angular Zone 之外执行,避免初始化阶段的大量异步操作无谓地触发变更检测。
多实例支持与默认实例
模块同时注册了AppCheck(默认实例)和AppCheckInstances(实例集合)两个 Provider:
defaultAppCheckInstanceFactory通过ɵgetDefaultInstanceOf<FirebaseAppCheck>(APP_CHECK_PROVIDER_NAME, provided, defaultApp)从已提供的实例中选出与默认 App 关联的那个;AppCheckInstances类(定义于 src/app-check/app-check.ts)则通过ɵgetAllInstancesOf<AppCheck>(APP_CHECK_PROVIDER_NAME)返回当前注册的全部 App Check 实例,其类型为interface AppCheckInstances extends Array<AppCheck> {}。
这意味着如果你的应用初始化了多个 Firebase App,每个 App 都可以有各自的 App Check 实例,而AppCheckInstances可以一次取回全部实例;provideAppCheck通过multi: true的 Provider 注册方式支持这种多实例场景。
版本登记与 RxJS 响应式访问
AppCheckModule构造函数与provideAppCheck都会调用registerVersion('angularfire', VERSION.full, 'app-check'),将 AngularFire 版本信息登记到 Firebase SDK 中,便于 Firebase 诊断与遥测时识别客户端版本。- src/app-check/app-check.ts 还导出了一个响应式入口:
export const appCheckInstance$ = timer(0, 300).pipe( concatMap(() => from(ɵgetAllInstancesOf<FirebaseAppCheck>(APP_CHECK_PROVIDER_NAME))), distinct(), );appCheckInstance$是一个 RxJS 可观察流:每 300ms 轮询一次已注册的 App Check 实例,并通过distinct()去重,只在下一次出现新实例时发出值。这为"等待 App Check 实例就绪后再执行操作"(例如在实例可用后立即获取 Token)提供了声明式的响应式方案,可直接配合AsyncPipe或takeUntil等 RxJS 操作符使用。
实践小结
综合官方文档与源码,在 Angular 应用中接入 App Check 的完整链路是:
- 运行
ng add @angular/fire完成 AngularFire 安装与项目配置(参见 docs/install-and-setup.md)。 - 在 app.config.ts 中通过
provideFirebaseApp+provideAppCheck注册默认 Firebase App 与 App Check 实例,并使用ReCaptchaV3Provider作为证明提供方。 - 在组件中
inject(AppCheck)获得实例,通过getToken、onTokenChanged、setTokenAutoRefreshEnabled等与官方 Firebase 一致的 API(从@angular/fire/app-check导入)完成 Token 获取、监听与自动刷新控制。 - 本地开发时无需担心 reCAPTCHA 校验——AngularFire 会在开发模式或 localhost 下自动启用调试 Token;服务端渲染场景则使用 Admin Token。
需要提醒的是:App Check 的 Token 最终要由你的后端(无论是 Cloud Functions、Cloud Run 还是自建服务)进行校验才能形成闭环保护。前端集成只是"证明客户端可信"的第一步,建议同时在后端启用 App Check 验证,并遵循 Firebase 官方文档对 reCAPTCHA Provider 的配置要求(如 site key 的获取与域名白名单设置),才能让这套防护真正生效。
相关源码入口:模块与 Provider 实现见 src/app-check/app-check.module.ts,实例抽象与响应式流见 src/app-check/app-check.ts,Zone 包装的 API 层见 src/app-check/firebase.ts,公开导出见 src/app-check/public_api.ts。
- 后端
【免费下载链接】angularfire
Angular + Firebase = ❤️
相关推荐
AngularFire Analytics 集成指南:在 Angular 应用中接入 Firebase Analytics
AngularFire Analytics 集成指南:在 Angular 应用中接入 Firebase Analytics Google Analytics 是
后端AngularFire 全面指南:在 Angular 应用中无缝集成 Firebase
AngularFire 全面指南:在 Angular 应用中无缝集成 Firebase 导读 AngularFire 是 Angular 官方生态中用于集成 F
后端Faker 实战指南:用 Faker::Movies::Departed 生成《无间道风云》演员、角色与经典台词
Faker 实战指南:用 Faker::Movies::Departed 生成《无间道风云》演员、角色与经典台词 导读 Faker::Movies::Depar
后端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考