路由守卫实现后页面刷新丢失路由信息,重定向至首页问题求助
路由权限守卫刷新页面时丢失路由信息,重定向至根路径
实现基于用户角色的路由权限守卫后,出现以下异常:
- 浏览器刷新页面或直接通过URL加载页面时,会被重定向至
index.html,currentUrl显示为"/",原路由信息丢失 - 页面间正常导航时组件加载无异常
路由权限守卫代码
canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { const user = this._authService._user?.profile.sub; const route = next.routeConfig?.path?.split('/')[0]; const currentUrl = this._router.url; return this.hasRight(user, route); } private hasRight(currentUserId: any, route: any): Promise<boolean | UrlTree> { return new Promise<boolean | UrlTree>((resolve, reject) => { this._securityService.apiSecurityHasRightPost(currentUserId, route).subscribe( (response: BooleanResponse) => { if (response.result!) { resolve(true); } else { resolve(this._router.createUrlTree(['/unauthorized'])); } }, (error) => { console.error('Error', error); resolve(false); } ); });}
子模块路由配置(应用守卫方式)
const routes: Routes = [ { path: '', component: MainComponent, children: [ { path: '', redirectTo: 'dashboard', pathMatch: 'full' }, { path: 'dashboard', component: DashboardComponent, canActivate: [AuthGuard] }, { path: 'test', component: NewtestpageComponent,canActivate:[RouteAccessControlGuard]}, { path: 'redirect', component: MainRedirectComponent }, { path: 'brand', component: BrandComponent,canActivate:[RouteAccessControlGuard] }, ]} ];
index.html中的base href
<base href="/">
根路由模块代码
const AUTH_ROUTES: Routes= [ { path: '', redirectTo:'unauthorized', pathMatch:'full'}, { path: 'unauthorized', component: UnauthorizedComponent }, { path: 'signin-callback', component: SigninCallbackComponent }, { path: 'signout-callback', component: SignoutCallbackComponent }, { path: 'silent-callback', component: SilentCallbackComponent }, ]; const routes: Routes = [ { path: '', redirectTo:'main', pathMatch:'full'}, { path: '', component: AuthLayoutComponent, children:AUTH_ROUTES}, { path: 'main',loadChildren: ()=>import('./main/main.module').then(m => m.MainModule), canActivate:[AuthGuard]}, { path: 'showroom/:id', component: ShowroomComponent}, ]; @NgModule({ imports: [RouterModule.forRoot(routes,{ onSameUrlNavigation: 'reload', })] })
已尝试的方案
- 调整异步逻辑,将
hasRight方法移至服务和解析器中,问题未解决
问题排查与解决方案
1. 修复路由信息获取逻辑
刷新页面时next.routeConfig?.path可能为空,导致权限校验失败触发默认重定向。改用state.url获取目标路由:
canActivate( next: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree { const user = this._authService._user?.profile.sub; // 从完整URL提取目标路由(示例:/main/test -> test) const targetPath = state.url.split('/')[2]; if (!user) { return this._router.createUrlTree(['/unauthorized']); } return this.hasRight(user, targetPath); }
2. 修正错误场景处理逻辑
当前请求出错时返回false会触发Angular默认重定向,改为明确重定向到未授权页面:
private hasRight(currentUserId: any, route: any): Promise<boolean | UrlTree> { return new Promise<boolean | UrlTree>((resolve) => { if (!route) { resolve(this._router.createUrlTree(['/unauthorized'])); return; } this._securityService.apiSecurityHasRightPost(currentUserId, route).subscribe( (response: BooleanResponse) => { resolve(response.result! ? true : this._router.createUrlTree(['/unauthorized'])); }, (error) => { console.error('权限校验请求出错', error); resolve(this._router.createUrlTree(['/unauthorized'])); } ); }); }
3. 调整根路由优先级
根路由存在两个空路径路由,导致匹配异常,修改为:
const routes: Routes = [ { path: '', redirectTo:'main', pathMatch:'full'}, // 给AUTH_ROUTES父路由指定非空路径 { path: 'auth', component: AuthLayoutComponent, children:AUTH_ROUTES}, { path: 'main',loadChildren: ()=>import('./main/main.module').then(m => m.MainModule), canActivate:[AuthGuard]}, { path: 'showroom/:id', component: ShowroomComponent}, ];
4. 移除冗余路由配置
onSameUrlNavigation: 'reload'可能导致刷新时路由重复解析,移除该配置:
@NgModule({ imports: [RouterModule.forRoot(routes)] })
内容的提问来源于stack exchange,提问作者Asdf
相关产品推荐
相关产品推荐

