Angular结合Firebase认证时Guard无法阻止已登录用户访问登录页
问题原因
你写的AnonymousGuard存在三个核心错误,导致路由阻塞:
- 缺少
@Injectable()装饰器,Angular依赖注入框架无法正确实例化守卫,路由解析直接进入pending状态 - 权限判断逻辑颠倒:你通过
map(authState => !!authState)得到的布尔值是「已登录为true、未登录为false」,而该守卫的需求是「未登录才允许访问登录页」,未登录时你返回了false,路由直接被拦截,无后续跳转逻辑,表现为页面卡住 - 未添加
take(1)操作符:Firebase的authState是长连接Observable,不会主动触发完成事件,路由守卫会一直等待Observable结束,进一步加剧阻塞问题
修复后的代码
完整AnonymousGuard代码
import { Injectable } from '@angular/core'; import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot, UrlTree } from '@angular/router'; import { Observable } from 'rxjs'; import { map, take } from 'rxjs/operators'; import { AuthentificationService } from '../services/authentification.service'; @Injectable({ providedIn: 'root' }) export class AnonymousGuard implements CanActivate { constructor( private authService: AuthentificationService, private router: Router) { } canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this.authService.user$ .pipe( take(1), // 只读取一次当前认证状态,主动结束Observable map(authState => { // 已登录用户禁止访问登录页,直接跳转至内部页 if (authState) { return this.router.parseUrl('/scanner'); } // 未登录用户允许访问 return true; }) ) } }
可选优化:原有AuthGuard同步调整
避免原有守卫出现同样的长期订阅、路由阻塞问题:
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { return this.authService.user$ .pipe( take(1), map(authState => { if (!authState) { return this.router.parseUrl('/sign-in'); } return true; }) ) }
修复完成后取消路由配置里sign-in路由的canActivate: [AnonymousGuard]注释即可正常运行。
内容的提问来源于stack exchange,提问作者Paul Serre
相关产品推荐
相关产品推荐

