Handling 401s globally with Angular

后端 未结 8 967
误落风尘
误落风尘 2020-11-28 18:50

In my Angular 2 project I make API calls from services that return an Observable. The calling code then subscribes to this observable. For example:

getCampai         


        
8条回答
  •  春和景丽
    2020-11-28 19:39

    To avoid the cyclic referencing issue that is caused by having services like "Router" being injected into an Http derived class, one must use the post-constructor Injector method. The following code is a working implementation of an Http service that redirects to Login route each time a REST API returns "Token_Expired". Note that it can be used as a substitution to the regular Http and as such, doesn't require to change anything in your application's already existing components or services.

    app.module.ts

      providers: [  
        {provide: Http, useClass: ExtendedHttpService },
        AuthService,
        PartService,
        AuthGuard
      ],

    extended-http.service.ts

    import { Injectable, Injector } from '@angular/core';
    import { Request, XHRBackend, RequestOptions, Response, Http, RequestOptionsArgs, Headers } from '@angular/http';
    import { Observable } from 'rxjs/Observable';
    import { Router } from '@angular/router';
    import { AuthService } from './auth.service';
    import 'rxjs/add/operator/catch';
    import 'rxjs/add/observable/throw';
    
    @Injectable()
    export class ExtendedHttpService extends Http {
        private router; 
        private authService;
    
      constructor(  backend: XHRBackend, defaultOptions: RequestOptions, private injector: Injector) {
        super(backend, defaultOptions);
      }
    
      request(url: string | Request, options?: RequestOptionsArgs): Observable {
     
        if (typeof url === 'string') {
          if (!options) {
            options = { headers: new Headers() };
          }
          this.setHeaders(options);
        } else {
          this.setHeaders(url);
        }
        console.log("url: " + JSON.stringify(url) +", Options:" + options);
    
        return super.request(url, options).catch(this.catchErrors());
      }
    
      private catchErrors() {
    
        return (res: Response) => {
            if (this.router == null) {
                this.router = this.injector.get(Router);
            }
            if (res.status === 401 || res.status === 403) {
                //handle authorization errors
                //in this example I am navigating to login.
                console.log("Error_Token_Expired: redirecting to login.");
                this.router.navigate(['signin']);
            }
            return Observable.throw(res);
        };
      }
    
      private setHeaders(objectToSetHeadersTo: Request | RequestOptionsArgs) {
          
          if (this.authService == null) {
                this.authService = this.injector.get(AuthService);
          }
        //add whatever header that you need to every request
        //in this example I could set the header token by using authService that I've created
         //objectToSetHeadersTo.headers.set('token', this.authService.getToken());
      }
    }

提交回复
热议问题