【问题标题】:Angular 4+ Guard with subscriptionAngular 4+ Guard 订阅
【发布时间】:2018-05-25 09:10:24
【问题描述】:

我的场景让我在激活路由时验证/登录 Windows 用户。因此,我只需验证用户是否已通过身份验证,如果没有,我会调用服务器生成令牌并期望向 canActivate() 返回 true,也许它无法按预期工作。

一段代码:

auth.guard.ts

import { Observable } from 'rxjs/Observable';
import { CanActivate, Router, ActivatedRouteSnapshot } from '@angular/router';
import { Injectable } from '@angular/core';
import { AuthService } from './../data/auth.service';
import { TokenService } from '../auth/token.service';
import { of } from 'rxjs/observable/of';

@Injectable()
export class AuthGuard implements CanActivate {

    constructor(
        private loginService: AuthService,
        private tokenService: TokenService,
        private router: Router) {        
    }

    canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
        const operation = route.data.operation;

        if (!this.tokenService.isAuthenticated() && !this.login()) {            
            console.log('canActive1: ', false);
            return of(false);
        }

        console.log('canActive: ', true);
        return of(true);
    }    

    login() {
        this.loginService.getToken().subscribe((user) => {
            console.log('token returned..');
            if (user && user.token) {
                this.tokenService.storeToken(user.token);
                return true;
            }
            return false;
        });
    }
}

控制台:

  • canActivate1: 假
  • 令牌返回..

【问题讨论】:

  • 嘿!答案如何,对你有帮助吗? :)

标签: angular typescript observable angular2-services


【解决方案1】:

这是异步的,因此控制台日志稍后出现。除此之外,您的问题是您试图从订阅返回数据,这是不可能的。你需要返回一个 Observable。

canActivate(route: ActivatedRouteSnapshot): Observable<boolean> {
    const operation = route.data.operation;

    return this.login().map(bool => {
      if(!bool && !this.tokenService.isAuthenticated()) {
        return false;
      }
      return true;
      }
    })
}    

login() {
  // use map instead!
  return this.loginService.getToken().map((user) => {
    console.log('token returned..');
    if (user && user.token) {
      this.tokenService.storeToken(user.token);
      return true;
    }
    return false;
  });
}

【讨论】:

    【解决方案2】:

    您没有返回 login() 方法的结果。试试这个吧。

    login(): Observable<boolean> {
        return this.loginService.getToken().take(1).subscribe((user) => {
            console.log('token returned..');
            if (user && user.token) {
                this.tokenService.storeToken(user.token);
                return true;
            }
            return false;
        });
    }
    

    【讨论】:

    • 使用这个方案,会导致执行guard时多次订阅。我认为这不是一个好的解决方案。
    【解决方案3】:

    首先,您必须使用 login() : Observable&lt;boolean 返回 login() 函数的结果,正如其他人正确提到的那样。

    其次,我能理解的问题在于这一行:-
    if (!this.tokenService.isAuthenticated() &amp;&amp; !this.login())

    我猜当你调用 tokenService.isAuthenticated() 时,你一定是在检查用户是否有一个令牌,对吧?

    因此,如果一个人没有获得令牌,那么 this.tokenService.isAuthenticated() 将返回 false,这就是您的 if (!this.tokenService.isAuthenticated() &amp;&amp; !this.login()) 也将返回 false 的方式,因为您应用了 AND 条件。

    调用 login() 函数将设置令牌,但在此之前,您的 tokenServiceisAuthenticated() 函数将返回 false 并且路由不会被激活

    【讨论】:

      猜你喜欢
      • 2019-11-13
      • 1970-01-01
      • 2018-07-13
      • 2017-11-25
      • 2021-05-06
      • 2018-08-08
      • 2018-11-23
      • 2018-11-26
      • 2020-10-11
      相关资源
      最近更新 更多