Angular NGXS权限守卫:如何解决用户状态竞态条件问题
解决NGXS权限守卫的竞态条件问题
你的问题根源在于守卫订阅到了SecurityState.getCurrentUser的初始null值,此时直接执行判断逻辑导致错误重定向,而没有等待用户状态异步加载完成。可以通过以下方式修改代码解决:
import { inject } from '@angular/core'; import { CanActivateFn, Router } from '@angular/router'; import { Store } from '@ngxs/store'; import { SecurityState } from './components/state/security.state'; import { filter, map, first } from 'rxjs'; export const authGuard: CanActivateFn = (route, state) => { const requiredRoles = route.data["roles"]; const router = inject(Router); const store = inject(Store); return store.select(SecurityState.getCurrentUser).pipe( // 过滤掉初始的null值,等待用户状态加载完成 filter(user => user !== null), // 只取一次值,避免内存泄漏 first(), map(user => { // 无角色要求且已登录,或用户拥有所需角色 if ((!requiredRoles && user) || user?.roles?.some(role => requiredRoles?.includes(role))) { return true; } // 根据实际情况调整:未登录跳登录页,权限不足跳forbidden const redirectUrl = user ? "/forbidden" : "/login"; router.navigate([redirectUrl]); return false; }) ); };
关键修改点说明:
filter(user => user !== null):确保守卫只在用户状态已加载(非null)时才执行判断逻辑,避免初始状态的误判。first():自动完成订阅,防止路由守卫长期持有订阅导致内存泄漏。- 区分未登录与权限不足的重定向:增加对用户是否存在的判断,未登录时跳转到登录页,权限不足才跳转到
/forbidden,更贴合常见业务逻辑(可根据你的实际需求调整)。
另外需要确认你的SecurityState中,用户状态的初始化逻辑是正确的——比如在应用启动时触发加载用户信息的action,保证守卫执行时用户状态能被正确加载。
内容的提问来源于stack exchange,提问作者Ilias Bgl
相关产品推荐
相关产品推荐

