【发布时间】:2018-01-18 23:55:12
【问题描述】:
Angular 2 路由器防护可以在数组中定义。例如:
<code>
canActivate: ['CanAlwaysActivateGuard','AuthGuard']
</code>
以下是我的问题:
- 两名守卫的执行顺序是什么。
- 如果我只想在 CanAlwaysActivateGuard 返回 true 时执行 AuthGuard,这可能吗。
【问题讨论】:
Angular 2 路由器防护可以在数组中定义。例如:
<code>
canActivate: ['CanAlwaysActivateGuard','AuthGuard']
</code>
以下是我的问题:
【问题讨论】:
如果你嵌套它们,你可以决定它们的顺序:
import { Routes } from '@angular/router';
const routes: Routes = [
{
path: '',
canActivate: [CanAlwaysActivateGuard],
children: [
{
path: '',
canActivate: [AuthGuard],
children: [
// (...)
],
}
],
}
];
在任何内部路由防护之前评估外部路由防护。
【讨论】:
对于当前版本,可以使用子路由器,例如:
{
path: 'your-path',
canActivate: [
CanAlwaysActivateGuard,
],
canActivateChild: [
AuthGuard,
],
children: [
]
}
【讨论】:
您还可以在 AuthGuard.canActivate() 之前继承保护运行 super.canActivate()。
在此示例中,两个类中的
canActivate()方法都返回Promise。
@Injectable({
providedIn: 'root',
})
class AuthGuard extends CanAlwaysActivateGuard implements CanActivate {
constructor(/*...*/) {
super(/*...*/);
}
async canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean | UrlTree> {
const result = await super.canActivate(next, state);
if (result === true) { // Check the expected result from the parent
return await this.logicOfYourAuthGuard(); // Run your logic and return it
}
return result; // Return the original result if logic of AuthGuard is not nedded
}
}
然后,在路由中,只使用AuthGuard。
其他选项是使用canActivateChild,因为canActivate 守卫在canActivateChild 之前运行。
【讨论】:
我遇到了这个问题,并在寻找答案时遇到了您的帖子。没有找到——今天有时间——我想出了一个我认为你可能会感兴趣的解决方案。我创建了一个“CompositeRouteGuard”:
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } from '@angular/router';
import {Injectable, Injector} from '@angular/core';
import { Observable } from "rxjs";
@Injectable()
export class CompositeRouteGuard implements CanActivate {
constructor( protected router: Router,
protected injector: Injector ) {
}
canActivate( route: ActivatedRouteSnapshot, state: RouterStateSnapshot ): Observable<boolean> {
var compositeCanActivateObservable: Observable<boolean> = Observable.of(true);
let routeGuards = route.data.routeGuards;
if(routeGuards){
for( var i = 0; i < routeGuards.length; i++ ){
let routeGuard = this.injector.get(routeGuards[i]);
let canActivateObservable = routeGuard.canActivate(route, state);
compositeCanActivateObservable = compositeCanActivateObservable.flatMap( (bool) => {
if(!bool){
return Observable.of(false);
}
else{
return canActivateObservable;
}
});
}
}
return compositeCanActivateObservable;
}
}
这需要在您的 routes.ts 中进行一些额外的配置。您需要在路由的数据元素中添加一个“routeGuards”数组。
const routes: Routes = [
{
path: '...',
component: AComponent,
data: { routeGuards: [ FooRouteGuard, BarRouteGuard, BazRouteGuard ] },
canActivate: [ CompositeRouteGuard ]
},
...
我只关心 canActivate 操作,但如果需要,您应该可以轻松扩展它,例如说“canDeactivate”。
现在我的路由守卫以“and”语义“按顺序”运行(所有路由都必须成功才能激活)。
【讨论】:
injector.get(...)已被弃用,最好使用这个:const routeGuard = this.injector.get<CanActivate>(routeGuards[i]);
两名守卫的执行顺序是什么。
它们将同步运行,无需相互等待。
如果我只想在 CanAlwaysActivateGuard 返回时执行 AuthGuard 是的,这可能吗?
不,目前的实现是不可能的。作为一种解决方法,您可以创建一个包装器守卫来按顺序运行您的守卫。
【讨论】: