Angular - Set headers for every request

前端 未结 19 1604
[愿得一人]
[愿得一人] 2020-11-22 07:43

I need to set some Authorization headers after the user has logged in, for every subsequent request.


To set headers for a particular request,



        
相关标签:
19条回答
  • 2020-11-22 08:32

    You can create your own http client with some authorization header:

    import {Injectable} from '@angular/core';
    import {HttpClient, HttpHeaders} from '@angular/common/http';
    
    @Injectable({
      providedIn: 'root'
    })
    export class HttpClientWithAuthorization {
    
      constructor(private http: HttpClient) {}
    
    createAuthorizationHeader(bearerToken: string): HttpHeaders {
      const headerDict = {
        Authorization: 'Bearer ' + bearerToken,
      }
      return new HttpHeaders(headerDict);
    }
    
    get<T>(url, bearerToken) {
      this.createAuthorizationHeader(bearerToken);
      return this.http.get<T>(url, {
        headers: this.createAuthorizationHeader(bearerToken)
      });
    }
    
    post<T>(url, bearerToken, data) {
      this.createAuthorizationHeader(bearerToken);
      return this.http.post<T>(url, data, {
        headers: this.createAuthorizationHeader(bearerToken)
      });
    }
    }
    

    And then inject it instead of HttpClient in your service class:

    @Injectable({
      providedIn: 'root'
    })
    export class SomeService {
    
      constructor(readonly httpClientWithAuthorization: HttpClientWithAuthorization) {}
    
      getSomething(): Observable<Object> {
        return this.httpClientWithAuthorization.get<Object>(url,'someBearer');
      }
    
      postSomething(data) {
        return this.httpClientWithAuthorization.post<Object>(url,'someBearer', data);
      }
    }
    
    0 讨论(0)
  • 2020-11-22 08:33

    There were some changes for angular 2.0.1 and higher:

        import {RequestOptions, RequestMethod, Headers} from '@angular/http';
        import { BrowserModule } from '@angular/platform-browser';
        import { HttpModule }     from '@angular/http';
        import { AppRoutingModule } from './app.routing.module';   
        import { AppComponent }  from './app.component';
    
        //you can move this class to a better place
        class GlobalHttpOptions extends RequestOptions {
            constructor() { 
              super({ 
                method: RequestMethod.Get,
                headers: new Headers({
                  'MyHeader': 'MyHeaderValue',
                })
              });
            }
          }
    
        @NgModule({
    
          imports:      [ BrowserModule, HttpModule, AppRoutingModule ],
          declarations: [ AppComponent],
          bootstrap:    [ AppComponent ],
          providers:    [ { provide: RequestOptions, useClass: GlobalHttpOptions} ]
        })
    
        export class AppModule { }
    
    0 讨论(0)
  • 2020-11-22 08:34

    This is how I did for setting token with every request.

    import { RequestOptions, BaseRequestOptions, RequestOptionsArgs } from '@angular/http';
    
    export class CustomRequestOptions extends BaseRequestOptions {
    
        constructor() {
            super();
            this.headers.set('Content-Type', 'application/json');
        }
        merge(options?: RequestOptionsArgs): RequestOptions {
            const token = localStorage.getItem('token');
            const newOptions = super.merge(options);
            if (token) {
                newOptions.headers.set('Authorization', `Bearer ${token}`);
            }
    
            return newOptions;
        }
    }
    

    And register in app.module.ts

    @NgModule({
        declarations: [
            AppComponent
        ],
        imports: [
            BrowserModule
        ],
        providers: [
            { provide: RequestOptions, useClass: CustomRequestOptions }
        ],
        bootstrap: [AppComponent]
    })
    export class AppModule { }
    
    0 讨论(0)
  • 2020-11-22 08:35

    HTTP interceptors are now available via the new HttpClient from @angular/common/http, as of Angular 4.3.x versions and beyond.

    It's pretty simple to add a header for every request now:

    import {
      HttpEvent,
      HttpInterceptor,
      HttpHandler,
      HttpRequest,
    } from '@angular/common/http';
    import { Observable } from 'rxjs';
     
    export class AddHeaderInterceptor implements HttpInterceptor {
      intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // Clone the request to add the new header
        const clonedRequest = req.clone({ headers: req.headers.append('Authorization', 'Bearer 123') });
    
        // Pass the cloned request instead of the original request to the next handle
        return next.handle(clonedRequest);
      }
    }
    

    There's a principle of immutability, that's the reason the request needs to be cloned before setting something new on it.

    As editing headers is a very common task, there's actually a shortcut for it (while cloning the request):

    const clonedRequest = req.clone({ setHeaders: { Authorization: 'Bearer 123' } });

    After creating the interceptor, you should register it using the HTTP_INTERCEPTORS provide.

    import { HTTP_INTERCEPTORS } from '@angular/common/http';
    
    @NgModule({
      providers: [{
        provide: HTTP_INTERCEPTORS,
        useClass: AddHeaderInterceptor,
        multi: true,
      }],
    })
    export class AppModule {}
    
    0 讨论(0)
  • 2020-11-22 08:35

    You can use canActive in your routes, like so:

    import { Injectable } from '@angular/core';
    import { Router } from '@angular/router';
    import { CanActivate } from '@angular/router';
    import { AuthService } from './auth.service';
    
    @Injectable()
    export class AuthGuard implements CanActivate {
    
      constructor(private auth: AuthService, private router: Router) {}
    
      canActivate() {
        // If user is not logged in we'll send them to the homepage 
        if (!this.auth.loggedIn()) {
          this.router.navigate(['']);
          return false;
        }
        return true;
      }
    
    }
    
    const appRoutes: Routes = [
      {
        path: '', redirectTo: '/deals', pathMatch: 'full'
      },
      {
        path: 'special',
        component: PrivateDealsComponent,
        /* We'll use the canActivate API and pass in our AuthGuard.
           Now any time the /special route is hit, the AuthGuard will run
           first to make sure the user is logged in before activating and
           loading this route. */
        canActivate: [AuthGuard]
      }
    ];
    

    Taken from: https://auth0.com/blog/angular-2-authentication

    0 讨论(0)
  • 2020-11-22 08:39

    After some investigation, I found the final and the most easy way is to extend BaseRequestOptions which I prefer.
    The following are the ways I tried and give up for some reason:
    1. extend BaseRequestOptions, and add dynamic headers in constructor(). It can not work if I login. It will be created once. So it is not dynamic.
    2. extend Http. Same reason as above, I can not add dynamic headers in constructor(). And if I rewrite request(..) method, and set headers, like this:

    request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
     let token = localStorage.getItem(AppConstants.tokenName);
     if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
      if (!options) {
        options = new RequestOptions({});
      }
      options.headers.set('Authorization', 'token_value');
     } else {
      url.headers.set('Authorization', 'token_value');
     }
     return super.request(url, options).catch(this.catchAuthError(this));
    }
    

    You just need to overwrite this method, but not every get/post/put methods.

    3.And my preferred solution is extend BaseRequestOptions and overwrite merge() :

    @Injectable()
    export class AuthRequestOptions extends BaseRequestOptions {
    
     merge(options?: RequestOptionsArgs): RequestOptions {
      var newOptions = super.merge(options);
      let token = localStorage.getItem(AppConstants.tokenName);
      newOptions.headers.set(AppConstants.authHeaderName, token);
      return newOptions;
     }
    }
    

    this merge() function will be called for every request.

    0 讨论(0)
提交回复
热议问题