我的路由器无法正常工作,当我转到 pageNotFound 页面并想要返回之前的步骤时,它会将我重定向到登录页面,如果您提供有关如何修复它的提示,我将不胜感激。反编译显示,从该页面返回时,authenticationguard - canActive() 中的方法返回 false,不幸的是我无法找出为什么用户读取不正确
export const routes: Routes = [
{
path: 'forbidden',
component: ForbiddenPageComponent,
},
{
path: 'auth',
loadChildren: () => import('./modules/auth/auth.module').then(mod => mod.AuthModule),
component: AuthComponent,
},
{
path: '',
canActivate: [AuthenticationGuard],
canActivateChild: [AuthorizationGuard],
children: [
{
path: 'task',
loadChildren: () => import('./modules/task/task.module').then(mod => mod.TaskModule),
},
{
path: 'order',
loadChildren: () => import('./modules/order/order.module').then(mod => mod.OrderModule),
},
{
path: '',
pathMatch: 'full',
redirectTo: 'task',
}
],
},
{
path: '**',
pathMatch: 'full',
component: PageNotFoundComponent
}
];
@Injectable({
providedIn: 'root',
})
export class AuthenticationGuard {
currentUser: OPLUser | null;
constructor(
private authService: AuthService,
private router: Router,
@Inject(APP_CONFIG) private appConfig: AppEnvConfiguration
) {
this.authService.currentUser$.subscribe(user => {
this.currentUser = user;
});
}
canActivate(): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
if (this.appConfig.skipLogin || (this.currentUser && this.currentUser.isAuthenticated())) {
return true;
}
this.router.navigate(['/auth'], { replaceUrl: true });
return false;
}
}
@Injectable({
providedIn: 'root',
})
export class AuthorizationGuard {
constructor(
private authService: AuthService,
private router: Router,
@Inject(APP_CONFIG) private appConfig: AppEnvConfiguration
) {}
/**
* Checks if user is authorized to activate this route.
* If not, user is redirected to 'forbidden' page.
*
* @param route
*/
canActivateChild(
route: ActivatedRouteSnapshot
): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
const currentUser = this.authService.currentUser$.getValue();
if (currentUser && currentUser.authenticatedAndAuthorized) {
if (this.appConfig.skipLogin) return true;
const routeRoleList: RouteRule = route && route.data ? route.data['roleList'] : null;
if (!routeRoleList || this.matchesRole(routeRoleList, currentUser)) {
return true;
} else {
this.router.navigate(['forbidden'], { skipLocationChange: true });
return false;
}
} else {
this.router.navigate(['forbidden'], { skipLocationChange: true });
return false;
}
}
/**
* Checks if user roles matches route role configuration.
* OneOf - checks any role.
* AllOf - checks all roles.
*
* @param routeRoleList - provided route role configuration.
* @param user - current user.
*/
matchesRole(routeRoleList: RouteRule, user: OPLUser | null): boolean {
let match = true;
if (routeRoleList.oneOf && routeRoleList.oneOf.length > 0) {
match = routeRoleList.oneOf.some(role => user?.hasRole(role));
}
if (routeRoleList.allOf && routeRoleList.allOf.length > 0) {
match = routeRoleList.oneOf.every(role => user?.hasRole(role));
}
return match;
}
}
发生这种情况是由于您配置路由的顺序所致。 Angular 路由器将按照当前 url 的顺序评估您在路由配置对象中定义的路径。这里发生的情况是路由器遇到了你的子路径和与 url 匹配的空路径(因为你没有
pathMatch: full
)。然后,它会尝试根据那里的重定向将您路由到 /task
,该重定向受 AuthenticationGuard
保护,因此您会被重定向到登录。
有两种方法可以解决此问题:
**
)移动到空路线上方,如下所示: ...
{
path: '**',
pathMatch: 'full',
component: PageNotFoundComponent
},
{
path: '',
canActivate: [AuthenticationGuard],
canActivateChild: [AuthorizationGuard],
children: [
{
path: 'task',
loadChildren: () => import('./modules/task/task.module').then(mod => mod.TaskModule),
},
{
path: 'order',
loadChildren: () => import('./modules/order/order.module').then(mod => mod.OrderModule),
},
{
path: '',
pathMatch: 'full',
redirectTo: 'task',
}
],
},
...
pathMatch: full
添加到空路径,如下所示: {
path: '',
pathMatch: 'full',
canActivate: [AuthenticationGuard],
canActivateChild: [AuthorizationGuard],
children: [
{
path: 'task',
loadChildren: () => import('./modules/task/task.module').then(mod => mod.TaskModule),
},
{
path: 'order',
loadChildren: () => import('./modules/order/order.module').then(mod => mod.OrderModule),
},
{
path: '',
pathMatch: 'full',
redirectTo: 'task',
}
],
},
如果您想自己调试路由器,可以通过启用路由器跟踪来实现。它将记录路由器经过的进程到控制台。您可以通过在根级别 app-routing.module.ts 中添加选项来做到这一点,如下所示:
@NgModule({
imports: [
RouterModule.forRoot(routes, {
enableTracing: true
}),
],
如果您使用的是独立的 Angular 应用程序(它使用
bootstrapApplication
方法引导您的 Angular 应用程序,您可以通过包含 withDebugTracing
中的 @angular/router
来启用路由器跟踪,如下所示:
provideRouter(APP_ROUTES,
withDebugTracing(),
),