【问题标题】:Where in Angular request lifetime to refresh JWT token在 Angular 请求生命周期中刷新 JWT 令牌的位置
【发布时间】:2019-10-31 19:59:55
【问题描述】:

我还是一个 Angular 新手。我想刷新访问令牌,但不确定在哪里进行。

我知道guards and interceptors。最好的地方在哪里?有没有我必须考虑的取舍?

这里的许多问题显示了在这两种情况下如何做到这一点,但不要讨论“为什么”。我认为刷新应该发生在守卫中,在请求周期的最开始,所以路由器知道是否“激活”。但是,大多数示例在拦截器中显示它(通过查看到期时间,或等待 401 然后刷新)。

任何建议将不胜感激。


更新
我知道“如何”,我需要了解的是为什么。刷新的正确位置在哪里?

守卫的工作是简单地检查用户是否登录,如果没有,则重定向到登录页面。

如果刷新令牌已过期,那么我认为守卫应该为 canActivate(ActivatedRouteSnapshot, RouterStateSnapshot) 返回 false,因为用户虽然经过身份验证,但不再拥有当前授权。

这就是为什么我倾向于把它放在后卫身上。但是大多数示例,包括下面的优秀示例,都显示了拦截器中的刷新。到那时,请求周期肯定已经很晚了吗?我在这里遗漏了什么 - 这只是风格问题,还是我应该考虑的角度请求周期还有更多?

【问题讨论】:

    标签: angular authentication jwt


    【解决方案1】:

    您可以使用 HttpInterceptor。由于每个 API 调用都会通过拦截器,您可以检查令牌是否仍然有效,继续 API 调用

    如果令牌过期,则显示 toastr 警报并阻止任何进一步的 API 调用。

    有关使用拦截器的更多信息,请访问10 ways to use Interceptors Angular 7 JWT Interceptor

    完整代码:

    http-interceptor.service.ts

    import { Injectable } from '@angular/core';
    import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/common/http';
    import { Observable } from 'rxjs';
    import { tap } from 'rxjs/operators';
    import { SessionService } from './session.service';
    import { Router } from '@angular/router';
    import { throwError } from 'rxjs';
    
    declare var toastr;
    
    @Injectable({
      providedIn: 'root'
    })
    export class HttpInterceptorService implements HttpInterceptor {
    
      constructor(private router: Router, private sessionService: SessionService) { }
    
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        var token = this.sessionService.getToken();
        if (token != null && this.sessionService.isTokenExpired()) {
          this.sessionService.logOut()
          toastr.warning("Session Timed Out! Please Login");
          this.router.navigate(['/login'])
          return throwError("Session Timed Out")
        } else {
    
          const authRquest = req.clone({
            setHeaders: {
              Authorization: 'Bearer ' + token
            }
          })
          return next.handle(authRquest)
            .pipe(
              tap(event => {
              }, error => {
              })
            )
        }
    
      }
    }
    

    app.module.ts

     providers: [
        {
            provide: HTTP_INTERCEPTORS,
            useClass: HttpInterceptorService,
            multi: true
          }
       ]
    

    session-service.ts

      getToken(): string {
        return localStorage.getItem('userToken');
      }
    
      getTokenExpirationDate(token: string): Date {
        token = this.getToken()
        const decoded = jwt_decode(token);
    
        if (decoded.exp === undefined) return null;
    
        const date = new Date(0);
        date.setUTCSeconds(decoded.exp);
        return date;
      }
    
      isTokenExpired(token?: string): boolean {
        if (!token) token = this.getToken();
        if (!token) return true;
    
        const date = this.getTokenExpirationDate(token);
        if (date === undefined) return false;
        return !(date.valueOf() > new Date().valueOf());
      }
    
      logOut(loginType?: string) {
        localStorage.removeItem('isLoggedin');
        localStorage.removeItem('userRole');
    
      }
    

    【讨论】:

    • 感谢这个非常好的和非常完整的例子!然而,我想知道的是,在拦截器中是否更好,就像你展示的那样,或者在警卫中。虽然我是 angular 新手,但我的直觉告诉我守卫是一个更好的位置,因为这是你决定是否激活路线的地方。但是大多数例子都是这样的,我不确定这是风格问题,还是我的理解中缺少一些东西......
    • Interceptor 是这样做的地方。在Guard 中,我们实际上评估了用户(登录用户)是否有权访问路由。而Guard是检查路由的地方,和http调用无关,token和http调用有关,应该在interceptors处理
    • 噢……现在我明白了。因此,守卫只是检查用户是否允许访问该路由 - 在那个阶段他是否实际登录是无关紧要的。感谢您的澄清! :)
    • 老实说,我检查了the repo 中您发布的那个链接,它证实了我的怀疑。我不确定守卫是最好的地方。它不执行某种 ACL 操作 - 它检查用户是否已登录,如果没有,则重定向到登录页面。如果刷新令牌已过期,则canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot) 的答案应为假。我相信守卫是这样做的地方,但我是新手,所以我可能错了。
    • 谢谢。这是从实时项目中复制的 :)
    猜你喜欢
    • 2020-11-06
    • 2020-02-26
    • 2021-04-06
    • 2017-10-11
    • 2016-10-14
    • 2018-12-23
    • 2020-12-19
    • 2021-06-04
    • 1970-01-01
    相关资源
    最近更新 更多