【问题标题】:Verify token with API in Angular8 canActivate method of AuthGuard使用 Angular8 中的 API 验证令牌 canActivate AuthGuard 方法
【发布时间】:2020-04-13 22:58:35
【问题描述】:

我想对某些路由的每个刷新请求进行一些验证。所以我使用 Angular AuthGuard。问题出在canActivate 方法中,我想使用在线 API 进行验证。

API 是 /token/verify,它只是获取 token 变量 (jwt) 并验证它是真还是假。 然后,如果验证未完成,将路由到 /login 页面,否则执行其余操作。

代码如下:

canActivate(next: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<boolean> | boolean {
let token = this.auth.getToken();
let url = '/token/verify/';
if (!token) {
  this.router.navigate(['/login']);
  return false;
}
this.auth.verifyToken().then(res => {
  return true;
}).catch(err => {
  this.router.navigate(['/login']);
  return false;
})

verifyToken方法是这样的:

verifyToken(): Promise<boolean> {
    let token = this.getToken();
    return !token ?
        new Promise<boolean>(resolve => {
            resolve(false);
            return false;
        }) :
        this.http.post(this.url + '/token/verify/', { 'token': token })
            .toPromise()
            .then((res) => {
                localStorage.data = JSON.stringify(res);//(res.json());
                return true;
            }
            ).catch((error) => {
                return false
            });
}

问题promise调用不起作用,会通过。我的意思是从本地存储检查它的第一部分工作正常。但是下一部分用在线 API 检查它是行不通的。并且authGuard 不会等待其响应来进行路由。

我想它应该是某种async/await 的方式。但是我做了一些测试,但都没有奏效。如果有人可以帮助我,我会很高兴。

【问题讨论】:

    标签: javascript angular async-await es6-promise auth-guard


    【解决方案1】:

    如果您改用Observables,我认为您将能够简化整个实现。

    如果您确实考虑了该提议,那么您的 verifyToken 方法可以重构为:

    import { of, Observable } from 'rxjs';
    
    verifyToken(): Observable<boolean> {
      const token = this.getToken();
      return token ? this.http
        .post(this.url + '/token/verify/', {
          'token': token
        })
        .pipe(
          tap(res => localStorage.data = JSON.stringify(res)),
          map(
            res => true,
            error => false
          )
        ) : of(false)
    }
    

    然后在你的 Guard 中,你只需这样做:

    canActivate(
      next: ActivatedRouteSnapshot,
      state: RouterStateSnapshot
    ): Observable < boolean > | Promise < boolean > | boolean {
      const token = this.auth.getToken();
      const url = "/token/verify/";
    
      if (!token) {
        this.router.navigate(['/login']);
        return false;
      }
    
      return this.auth.verifyToken().pipe(
        catchError(err => {
          console.log('Handling error locally and rethrowing it...', err);
          this.router.navigate(['/login']);
          return of(false);
        })
      );
    
    }
    

    这里有一个Working Demo 供您参考。

    【讨论】:

    • 感谢您花时间撰写详细的回复。但是你能检查一下 canActivate 最后一个return 语句吗?它似乎需要一些改变。它给出了这个错误Argument type MonoTypeOperatorFunction&lt;unknown&gt; is not assignable...你能再检查一次吗?
    • @RezaTorkamanAhmadi,请尝试更新后的答案。我已将if 条件放在{}
    • 不,还是同样的错误。我不应该改用pipecatch 方法吗?
    • @RezaTorkamanAhmadi,对此感到抱歉。我已经用正确的代码和一个示例工作演示更新了我的答案,供您参考。请检查是否有帮助。
    • 我也可以让它与catchError一起工作。请也验证我的更改。真的很感激。在你的帮助下,我能够解决它。 :)
    猜你喜欢
    • 2017-11-19
    • 2021-08-13
    • 2017-05-09
    • 1970-01-01
    • 2016-09-06
    • 1970-01-01
    • 2016-01-01
    • 2021-06-03
    • 2014-06-14
    相关资源
    最近更新 更多