Angular AuthGuard 不会 return 来自内部订阅的 UrlTree
Angular AuthGuard does not return UrlTree from inside subscription
我正在尝试实施 UrlTree
以在防护失败时重定向用户。
this.authService.isAuthenticated()
returns 可观察到。
以下内容不起作用,但控制台 false
.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
this.authService.isAuthenticated().subscribe(isAuthenticated => {
if (isAuthenticated) {
return true;
} else {
console.log(isAuthenticated);
return this.router.createUrlTree(['auth/sign-in']);
}
});
return false;
}
但如果我删除订阅,则以下内容有效:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
return this.router.createUrlTree(['auth/sign-in']);
}
不知道您需要重定向用户。所以使用这个函数:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.isAuthenticated().pipe(
take(1),
map(user => !!user), // Converting object to a boolean
tap(loggedIn => {
// If you not return any value
// function will return loggedIn boolean value
if (!loggedIn) {
this.router.navigate(['/login'])
}
})
);
}
您不能 return 从内部订阅(无论如何)。 Route guard 可以 return 布尔值或布尔值的可观察值。因此,在您的情况下,您需要 return 一个可观察的布尔值。还值得一提的是,在您当前的代码中,由于这是异步的,因此无论登录状态如何,您当前 returning 都是 always false
,为什么?获得认证状态需要 x 时间,所以 false
每次都被 returned,angular 不等待响应,只是继续下一个可用代码,它在您当前的代码中是 return false;
。
因此,如前所述,return 是一个可观察对象,即使用 map
而不是 subscribe
:
import { map, take } from 'rxjs/operators';
// ....
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.isAuthenticated()
.pipe(
take(1),
map(isAuthenticated => {
if (isAuthenticated) {
return true;
}
// no need for else, if above is truthy, further code is not executed
this.router.createUrlTree(['auth/sign-in']);
return false;
})
);
}
@AJT82 在 Angular 8 中的回答对我不起作用。
返回带有 parseUrl
和 return 的 UrlTree 和 true
是唯一可行的方法。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.auth$.pipe(
map((authState: AuthState) => {
console.log('=========root guard=============');
if (!authState.isLoggedIn) {
return this.router.parseUrl('/auth/login');
}
if (state.url === '' || state.url === '/') {
if (authState.accessGroups.includes(AccessGroup.ADMIN)) {
return this.router.parseUrl('/post/list');
}
if (authState.accessGroups.includes(AccessGroup.REEF)) {
return this.router.parseUrl('/reef');
}
}
return true;
})
);
而且我真的不明白为什么 returning UrlTree 是不够的。如果我不 return true
路由器将被阻止。
很奇怪。
设置 UrlTree 然后 returning True 也没有用。只有 returning UrlTree
和 return true
对我有用。
我正在尝试实施 UrlTree
以在防护失败时重定向用户。
this.authService.isAuthenticated()
returns 可观察到。
以下内容不起作用,但控制台 false
.
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
this.authService.isAuthenticated().subscribe(isAuthenticated => {
if (isAuthenticated) {
return true;
} else {
console.log(isAuthenticated);
return this.router.createUrlTree(['auth/sign-in']);
}
});
return false;
}
但如果我删除订阅,则以下内容有效:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): boolean | UrlTree {
return this.router.createUrlTree(['auth/sign-in']);
}
不知道您需要重定向用户。所以使用这个函数:
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.isAuthenticated().pipe(
take(1),
map(user => !!user), // Converting object to a boolean
tap(loggedIn => {
// If you not return any value
// function will return loggedIn boolean value
if (!loggedIn) {
this.router.navigate(['/login'])
}
})
);
}
您不能 return 从内部订阅(无论如何)。 Route guard 可以 return 布尔值或布尔值的可观察值。因此,在您的情况下,您需要 return 一个可观察的布尔值。还值得一提的是,在您当前的代码中,由于这是异步的,因此无论登录状态如何,您当前 returning 都是 always false
,为什么?获得认证状态需要 x 时间,所以 false
每次都被 returned,angular 不等待响应,只是继续下一个可用代码,它在您当前的代码中是 return false;
。
因此,如前所述,return 是一个可观察对象,即使用 map
而不是 subscribe
:
import { map, take } from 'rxjs/operators';
// ....
canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> {
return this.authService.isAuthenticated()
.pipe(
take(1),
map(isAuthenticated => {
if (isAuthenticated) {
return true;
}
// no need for else, if above is truthy, further code is not executed
this.router.createUrlTree(['auth/sign-in']);
return false;
})
);
}
@AJT82 在 Angular 8 中的回答对我不起作用。
返回带有 parseUrl
和 return 的 UrlTree 和 true
是唯一可行的方法。
canActivate(
next: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<boolean | UrlTree> | Promise<boolean | UrlTree> | boolean | UrlTree {
return this.authService.auth$.pipe(
map((authState: AuthState) => {
console.log('=========root guard=============');
if (!authState.isLoggedIn) {
return this.router.parseUrl('/auth/login');
}
if (state.url === '' || state.url === '/') {
if (authState.accessGroups.includes(AccessGroup.ADMIN)) {
return this.router.parseUrl('/post/list');
}
if (authState.accessGroups.includes(AccessGroup.REEF)) {
return this.router.parseUrl('/reef');
}
}
return true;
})
);
而且我真的不明白为什么 returning UrlTree 是不够的。如果我不 return true
路由器将被阻止。
很奇怪。
设置 UrlTree 然后 returning True 也没有用。只有 returning UrlTree
和 return true
对我有用。