我已经在我的angular 6应用程序( app.routing.ts )中创建了一个路由模块。我已经向我的应用程序添加了多个路由,但是没有在我的路由的任何地方使用child
指令(不好的做法是,但是现在我还在应用程序的另一部分添加了动态路由,并且不想更改整个结构,因为这样做会花费很长时间。
我想知道是否有一种方法可以全局使用canActivate: [AuthGuardService]
(用于检查用户是否已登录)除根目录以外的所有路由。我已经签出了类似的答案here,但防护罩似乎无法正常工作,仍然可以加载页面。 (也许是因为我没有任何子路线)。
此外,我认为该方法可能也不是最好的方法,因为在这种情况下,Guard(消耗层)能够知道哪一层正在使用它的方法(哪个imo并不是mvc模式的最佳方法,当然,我对路由模块所做的工作也不是很好)。有没有办法以更清洁的方式实现这一目标?
app.routing.ts
export const routes: Routes = [
{
path: 'main',
component: MainComponent,
pathMatch: 'full'
},
{
path: 'search/:id',
component: GlobalSearchComponent
},
{
path: '',
canActivate: [AuthGuardService],
component: LoginComponent,
},
{
path: 'reset',
component: ResetPasswordComponent
},
{
path: 'forgot',
component: ForgotPasswordComponent
},
{
path: 'knowledge-base/create',
component: KnowledgeBaseCreateComponent
},
{
path: 'knowledge-base/detail/:id',
component: KnowledgeBaseDetailComponent
},
{
path: 'knowledge-base/edit/:id',
component: KnowledgeBaseEditComponent
},
{
path: 'projects/detail/:id',
component: ProjectDetailComponent
},
{
path: 'projects/create',
component: ProjectCreateComponent
},
{
path: '**',
component: NotFoundComponent
}
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
})
export class AppRoutingModule { }
authguard.service
import { Injectable } from '@angular/core';
import { Router, CanActivate, ActivatedRouteSnapshot, RouterStateSnapshot } from '@angular/router';
import { ToastrService } from 'ngx-toastr';
import { TranslatePipe } from 'src/app/pipes/translate/translate.pipe';
/**
* This injector provides the auth-guard service throughout the application.
*/
@Injectable({
providedIn: 'root'
})
/**
* The auth guard service is used to prevent unauthenticated users from
* accessing restricted routes, it's used in app.routing.ts to protect the home
* page route
*/
export class AuthGuardService {
/**
* The constructor initializes the ToastrService & TranslatePipe in the component.
*/
constructor(private toastr: ToastrService,
private translate: TranslatePipe,
private router: Router) { }
/**
* This method checks if the user is authorized to access a certain route.
*
* @param route
* @param state
* @return
*/
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
if (localStorage.getItem('jwtToken')) {
return true;
} else {
if (this.router.url !== '/') {
let error = this.translate.transform("generic[responses][error][401]");
this.toastr.warning(error);
this.router.navigate(['']);
} else {
return true;
}
}
}
}
答案 0 :(得分:2)
达到此目的的干净方法是将它们包装在一条路由的children
中。您说您知道这一点,但是您还提到这会导致您更改整个结构-并非如此。您可能想过使用loadChildren
,这实际上会带来更大的变化。这是一个使用knowledge-base
children
路线的示例
{
path: 'knowledge-base',
canActivate: [AuthGuardService],
children: [
{
path: '',
redirectTo: 'knowledge-base/create',
pathMatch: 'full'
},
{
path: 'create',
component: KnowledgeBaseCreateComponent
},
{
path: 'detail/:id',
component: KnowledgeBaseDetailComponent
},
{
path: 'edit/:id',
component: KnowledgeBaseEditComponent
}
]
}
这就是您需要更改的所有内容,基本上只需将其包装在children
中即可。您也可以将此方法应用于其他路线。或者,如果您只想使用RouterGuard
一次,则可以创建类似path: 'main'
的东西,然后将所有内容包装在那里
答案 1 :(得分:2)
根据最佳做法,您应该按层次结构组织路由,并使用子级嵌套子级路由/组件。路线守卫也以相同的方式工作,这就是为什么我们拥有canActivateChild守卫。
您仍然可以将路由重构为仅具有父子(嵌套)关系,并使用canActivateChild保护。我认为改变这一点不会有重大影响。如果您进行延迟加载并在模块中分隔路由,则可能会发生很大的变化。
canActivateChild(route: ActivatedRouteSnapshot, state: RouterStateSnapshot):
Observable<boolean> | Promise<boolean> | boolean {
return this.canActivate(route, state);
}
{ path: 'servers', canActivateChild: [AuthGuard], component: ServersComponent, children: [
{ path: ':id', component: ServerComponent, resolve: { server: ServerResolver } },
{ path: ':id/edit', component: EditServerComponent, canDeactivate: [canDeactivateGuard] }
]}