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 对我有用。