最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to show an alert or toaster message when the JWT token expires in Angular 7 - Stack Overflow

programmeradmin1浏览0评论

When a JWT token expires, the web app should show an alert or modal pop up, then it should redirect to login page. Currently I am using toaster message.

I have many api calls in my ponent. I get many toaster messages 'token expired'. I should show a message only and redirect to login page. tell me your good idea. I have some articles in the internet. But I could not get those things clearly.

import {
    HttpEvent,
    HttpInterceptor,
    HttpHandler,
    HttpRequest,
    HttpResponse,
    HttpErrorResponse
   } from '@angular/mon/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);
          })
        );
    }
   }

When a JWT token expires, the web app should show an alert or modal pop up, then it should redirect to login page. Currently I am using toaster message.

I have many api calls in my ponent. I get many toaster messages 'token expired'. I should show a message only and redirect to login page. tell me your good idea. I have some articles in the internet. But I could not get those things clearly.

import {
    HttpEvent,
    HttpInterceptor,
    HttpHandler,
    HttpRequest,
    HttpResponse,
    HttpErrorResponse
   } from '@angular/mon/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);
          })
        );
    }
   }
Share Improve this question edited Mar 31, 2020 at 19:16 halfer 20.4k19 gold badges109 silver badges202 bronze badges asked May 10, 2019 at 8:21 Kumaresan PerumalKumaresan Perumal 1,9602 gold badges30 silver badges39 bronze badges 2
  • Why don't use router.navigate in your first branch, instead of just return? The cleaner way would be to factor out this behaviour in a specific service, this way you always call the same behavior, instead of duplicating it in several branches. – Qortex Commented May 10, 2019 at 8:31
  • Since all your APIs use JWT token for authentication, it may be a good idea to first check the validity of the token and then proceeds for other APIs calls. – Deep Commented May 10, 2019 at 8:39
Add a ment  | 

1 Answer 1

Reset to default 5

You can use HttpInterceptor. Since every API call passes trough interceptor, you can check if the token is still valid, proceed with the API call

If the token expired, show toastr alert and prevent any further API call.

For more info on using interceptor, visit this 10 ways to use Interceptors and Angular 7 JWT Interceptor

Complete Code:

http-interceptor.service.ts

import { Injectable } from '@angular/core';
import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse } from '@angular/mon/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');

  }
发布评论

评论列表(0)

  1. 暂无评论