Angular2:如何使用路由器"reload"页面(重新检查可以激活)?



我有路由器,里面有canActivate: [ AuthGuard ]和验证AuthGuard

如何强制检查同一路由器网址中的canActivate

例如:当前路线/admin,我有类似session expired的事件。我有会话签入AuthGuard但此检查仅在我执行.navigate(...)时激活。如何在同一位置强制运行canActivate

我试过:this.router.navigate([ this.router.url ]);但角度检查相同的位置,什么也不做。

附言当我得到session expired event时,我可以找到"登录页面"或其他页面,但我AuthGuard内有所有重定向,我不想在所有其他事件中重复相同的重定向,我需要就像location.reload()一样但在 Angular2 路由中。

主要问题听起来像:如何在当前位置强制重新运行canActivate守卫?

我的临时解决方案:

auth.service.ts

import { Injectable, Injector } from '@angular/core';
import { ActivatedRoute, Router, RouterStateSnapshot } from '@angular/router';
@Injectable()
export class AuthService {
constructor(private route: ActivatedRoute,
private router: Router,
private injector: Injector) {
this.forceRunAuthGuard();
}
// Dirty hack for angular2 routing recheck
private forceRunAuthGuard() {
if (this.route.root.children.length) {
// gets current route
const curr_route = this.route.root.children[ '0' ];
// gets first guard class
const AuthGuard = curr_route.snapshot.routeConfig.canActivate[ '0' ];
// injects guard
const authGuard = this.injector.get(AuthGuard);
// makes custom RouterStateSnapshot object
const routerStateSnapshot: RouterStateSnapshot = Object.assign({}, curr_route.snapshot, { url: this.router.url });
// runs canActivate
authGuard.canActivate(curr_route.snapshot, routerStateSnapshot);
}
}
}

app.routes.ts

{ path: 'faq', canActivate: [ AuthGuard ], component: FaqComponent },
{ path: 'about', canActivate: [ AuthGuard ], component: AboutUsComponent },
{ path: 'upgrade', canActivate: [ AuthGuard ], component: UpgradeComponent },

此代码再次运行AuthGuard

不幸的是,@mixalbl4的答案在今天仍然适用,但我会给它一个更通用的方法,下面的代码将适用于任何AuthGuard:

import { Injectable, Injector } from "@angular/core";
import { ActivatedRoute, CanActivate, CanActivateChild, Router, RouterStateSnapshot, UrlTree } from "@angular/router";
import { concat, concatMap, from, isObservable, last, Observable, of, skip, takeWhile } from "rxjs";
@Injectable()
export class AuthService{
protected routeSnapshot: RouterStateSnapshot;
constructor(
protected route: ActivatedRoute,
protected injector: Injector,
protected router: Router){
this.routeSnapshot = Object.assign({}, this.route.snapshot, { url: this.router.url });
}
public checkActivation(){
this.checkRouteActivation(this.route).subscribe(a => {
if(a !== true){
if(a === false)
a = this.router.parseUrl("DEFAULT_ROUTE"); // Route to redirect to on activation fail, if not specified by guard
this.router.navigateByUrl(a as UrlTree);
}
});
}
private checkRouteActivation(route: ActivatedRoute):Observable<boolean | UrlTree>{
let conditions:Observable<boolean | UrlTree>[] = [];
// Check own activation
if(route.routeConfig){
if(route.routeConfig.canActivate?.length ?? 0 > 0)
conditions.push(...route.routeConfig.canActivate!.map(a => this.validateGuard(a, route, false)));
if(route.routeConfig.canActivateChild?.length ?? 0 > 0)
conditions.push(...route.routeConfig.canActivateChild!.map(ac => this.validateGuard(ac, route, true)));
}
// Add last true (if does not have any activations or parents)
if(conditions.length == 0)
conditions.push(of(true));
let ownObservable = concat(...conditions).pipe(takeWhile(v => v === true, true), last());
// Validate parent if present
if(route.parent)
return this.checkRouteActivation(route.parent).pipe(concatMap(v => v === true ?
ownObservable :
of(v)));
else
return ownObservable;
}
private validateGuard(guardToken: any, route: ActivatedRoute, child:boolean):Observable<boolean | UrlTree>{
var guard: (CanActivate & CanActivateChild) = this.injector.get(guardToken);

let result:Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree;
if(!child)
result = guard.canActivate(route.snapshot, this.routeSnapshot);
else
result = guard.canActivateChild(route.snapshot, this.routeSnapshot);
if(isObservable(result))
return result;
else if(typeof (result as any)?.then === 'function') // check if is promise
return from(result as Promise<boolean | UrlTree>);
else
return of(result as boolean | UrlTree);
}
}

相关内容

最新更新