【问题标题】:How to show an alert or toaster message when the JWT token expires in Angular 7当 JWT 令牌在 Angular 7 中过期时如何显示警报或烤面包机消息
【发布时间】:2019-09-28 02:52:31
【问题描述】:

当 JWT 令牌过期时,Web 应用程序应显示alert 或模式弹出窗口,然后它应重定向到登录页面。目前我正在使用烤面包机消息。

我的组件中有许多 api 调用。我收到许多烤面包机消息“令牌已过期”。我应该只显示一条消息并重定向到登录页面。告诉我你的好主意。我在网上有一些文章。但我无法清楚地了解这些内容。

import {
    HttpEvent,
    HttpInterceptor,
    HttpHandler,
    HttpRequest,
    HttpResponse,
    HttpErrorResponse
   } from '@angular/common/http';
import { Observable, throwError } from 'rxjs';
import { retry, catchError } from 'rxjs/operators';
import { Router } from '@angular/router';
import { ToastrManager } from 'ng6-toastr-notifications';
import { Injectable } from '@angular/core';
import { JwtDecoderService } from './jwt-decoder.service';

@Injectable()
export class HttpErrorInterceptor implements HttpInterceptor {

    constructor(public router: Router,
                public toastr: ToastrManager,
                private jwtDecoder: JwtDecoderService, ) {
    }

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
      if (localStorage.getItem('isLoggedin') === 'false' && !this.jwtDecoder.isTokenExpired()) {
        this.toastr.warningToastr('Token expired');
        return;
      }
      return next.handle(request)
        .pipe(
          catchError((error: HttpErrorResponse) => {
            let errorMessage = '';
            if (error.error instanceof ErrorEvent) {
              // client-side error
              errorMessage = `Error: ${error.error.message}`;
            } else {
              // server-side error
              errorMessage = `Error Code: ${error.status}\nMessage: ${error.message}`;
              if (error.status === 404) {
                this.toastr.warningToastr('Server Not Found');
                this.router.navigate(['/login']);
              }
              if (error.status === 412) {
                this.toastr.warningToastr('Token expired');
                this.router.navigate(['/login']);
              }
              // if (error.status === 500 || error.status === 400) {
              //   this.toastr.errorToastr('We encountered a technical issue');
              // }
            }
            // return throwError(errorMessage);
            return throwError(error);
          })
        );
    }
   }

【问题讨论】:

  • 为什么不在你的第一个分支中使用router.navigate,而不仅仅是return?更简洁的方法是在特定服务中排除这种行为,这样你总是调用相同的行为,而不是在多个分支中复制它。
  • 由于您的所有 API 都使用 JWT 令牌进行身份验证,因此最好先检查令牌的有效性,然后再进行其他 API 调用。

标签: javascript angular angular7 angular-http-interceptors


【解决方案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');

  }

【讨论】:

  • 我有一个疑问。 apicalls 只通过拦截器吗?或者我从云中获得了许多库和图像。我的意思是来自互联网。那么boostrap、jquery等图片和库也会通过拦截器吗????
  • 仅 API 调用。您可以通过拦截器设置身份验证令牌、显示加载程序等。如果添加拦截器,所有API调用都会通过它
  • @GeorgKastenhofer npmjs.com/package/jwt-decode
猜你喜欢
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 2019-08-05
  • 1970-01-01
  • 1970-01-01
  • 2021-03-10
  • 2012-12-16
  • 1970-01-01
相关资源
最近更新 更多