Angular Firebase:刷新时登录页面闪烁问题(AuthGuard + redirectUnauthorizedTo)
Angular 结合 Firebase Auth 刷新已认证路由时登录页闪烁问题
问题描述
刷新已认证路由页面时,登录页面会短暂闪烁后才重定向到目标URL。期望效果:仅当用户未认证时显示登录页面,已认证用户刷新页面时应直接停留在当前页面。
版本信息
- Angular: 17.3.4
- Node: 21.7.1
- @angular/fire: 17.0.1
相关代码
app.routes.ts
import { AuthGuard, redirectLoggedInTo, redirectUnauthorizedTo } from '@angular/fire/auth-guard'; const redirectUnauthorizedToLogin = () => redirectUnauthorizedTo(['/login']); const redirectLoggedInToHome = () => redirectLoggedInTo(['']); export const routes: Routes = [ { path: '', component: HomeComponent, canActivate: [AuthGuard], data: { authGuardPipe: redirectUnauthorizedToLogin }, }, // ... 其他路由 ];
app.config.ts
import { ApplicationConfig } from '@angular/fire/compat'; import { initializeApp } from 'firebase/app'; import { getAuth } from 'firebase/auth'; export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideHttpClient(withInterceptors([bearerTokenInterceptor])), importProvidersFrom([ provideFirebaseApp(() => initializeApp(environment.firebaseConfig)), provideAuth(() => getAuth()), ]), ], };
问题现象

解决方法
1. 延迟应用初始化,等待Auth状态加载完成
Firebase Auth在页面刷新时需要时间恢复用户会话,导致默认AuthGuard初始判定用户未认证,触发登录页跳转,等会话恢复后再重定向回目标页,造成闪烁。可以通过APP_INITIALIZER等待Auth状态初始化完成后再启动应用。
修改app.config.ts:
import { ApplicationConfig, APP_INITIALIZER } from '@angular/core'; import { initializeApp } from 'firebase/app'; import { getAuth, onAuthStateChanged } from 'firebase/auth'; import { firstValueFrom } from 'rxjs'; // 定义初始化函数,等待Auth状态稳定 const initializeAuth = () => { const auth = getAuth(); return () => firstValueFrom(new Promise(resolve => onAuthStateChanged(auth, resolve))); }; export const appConfig: ApplicationConfig = { providers: [ provideRouter(routes), provideHttpClient(withInterceptors([bearerTokenInterceptor])), importProvidersFrom([ provideFirebaseApp(() => initializeApp(environment.firebaseConfig)), provideAuth(() => getAuth()), ]), // 添加APP_INITIALIZER拦截应用启动,等待Auth初始化 { provide: APP_INITIALIZER, useFactory: initializeAuth, deps: [], multi: true } ], };
2. 自定义AuthGuard,基于稳定的Auth状态判定
替换@angular/fire的默认AuthGuard,自定义守卫逻辑,确保在Auth状态稳定后再做路由判定:
创建auth.guard.ts:
import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; import { Auth, authState } from '@angular/fire/auth'; import { map, take } from 'rxjs'; export const authGuard: CanActivateFn = (route, state) => { const auth = inject(Auth); const router = inject(Router); return authState(auth).pipe( take(1), map(user => { if (user) { return true; } else { return router.createUrlTree(['/login']); } }) ); };
修改app.routes.ts使用自定义守卫:
import { authGuard } from './auth.guard'; export const routes: Routes = [ { path: '', component: HomeComponent, canActivate: [authGuard], }, // ... 其他路由 ];
3. 添加全局加载占位(可选)
在根组件中添加加载状态,Auth初始化完成前显示加载动画,避免登录页闪烁:
app.component.html:
@if (!authInitialized) { <div class="loading-container"> <div class="loading-spinner">加载中...</div> </div> } @else { <router-outlet></router-outlet> }
app.component.ts:
import { Component, inject, OnInit } from '@angular/core'; import { Auth, authState } from '@angular/fire/auth'; import { firstValueFrom } from 'rxjs'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent implements OnInit { authInitialized = false; private auth = inject(Auth); async ngOnInit() { await firstValueFrom(authState(this.auth)); this.authInitialized = true; } }
内容的提问来源于stack exchange,提问作者abus
相关产品推荐
相关产品推荐

