我需要在用户登录后为每个后续请求设置一些授权头。


为特定请求设置头信息,

import {Headers} from 'angular2/http';
var headers = new Headers();
headers.append(headerName, value);

// HTTP POST using these headers
this.http.post(url, data, {
  headers: headers
})
// do something with the response

参考

但是,以这种方式为每个请求手动设置请求头是不可行的。

我如何设置头设置一旦用户登录,也删除注销这些头?


当前回答

在Angular 2.1.2中,我通过扩展Angular Http来解决这个问题:

import {Injectable} from "@angular/core";
import {Http, Headers, RequestOptionsArgs, Request, Response, ConnectionBackend, RequestOptions} from "@angular/http";
import {Observable} from 'rxjs/Observable';

@Injectable()
export class HttpClient extends Http {

  constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {

    super(_backend, _defaultOptions);
  }

  _setCustomHeaders(options?: RequestOptionsArgs):RequestOptionsArgs{
    if(!options) {
      options = new RequestOptions({});
    }
    if(localStorage.getItem("id_token")) {

      if (!options.headers) {

        options.headers = new Headers();


      }
      options.headers.set("Authorization", localStorage.getItem("id_token"))
    }
    return options;
  }


  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    options = this._setCustomHeaders(options);
    return super.request(url, options)
  }
}

然后在我的应用程序提供者中,我可以使用自定义工厂来提供“Http”

import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';
import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';//above snippet

function httpClientFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions): Http {
  return new HttpClient(xhrBackend, requestOptions);
}

@NgModule({
  imports:[
    FormsModule,
    BrowserModule,
  ],
  declarations: APP_DECLARATIONS,
  bootstrap:[AppComponent],
  providers:[
     { provide: Http, useFactory: httpClientFactory, deps: [XHRBackend, RequestOptions]}
  ],
})
export class AppModule {
  constructor(){

  }
}

现在我不需要声明每个Http方法,可以在整个应用程序中正常使用Http。

其他回答

const headers = new HttpHeaders()
  .set('content-type', 'application/json')
  .set('x-functions-key', '');

return this.http.get<Person[]>(baseUrl, {
      headers: headers,
    });

使用append方法将新值附加到现有值集

headers.append('Access-Control-Allow-Origin', '*')

你可以在你的路由中使用canActive,如下所示:

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]
  }
];

摘自:https://auth0.com/blog/angular-2-authentication

在Angular 2.1.2中,我通过扩展Angular Http来解决这个问题:

import {Injectable} from "@angular/core";
import {Http, Headers, RequestOptionsArgs, Request, Response, ConnectionBackend, RequestOptions} from "@angular/http";
import {Observable} from 'rxjs/Observable';

@Injectable()
export class HttpClient extends Http {

  constructor(protected _backend: ConnectionBackend, protected _defaultOptions: RequestOptions) {

    super(_backend, _defaultOptions);
  }

  _setCustomHeaders(options?: RequestOptionsArgs):RequestOptionsArgs{
    if(!options) {
      options = new RequestOptions({});
    }
    if(localStorage.getItem("id_token")) {

      if (!options.headers) {

        options.headers = new Headers();


      }
      options.headers.set("Authorization", localStorage.getItem("id_token"))
    }
    return options;
  }


  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    options = this._setCustomHeaders(options);
    return super.request(url, options)
  }
}

然后在我的应用程序提供者中,我可以使用自定义工厂来提供“Http”

import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';
import { RequestOptions, Http, XHRBackend} from '@angular/http';
import {HttpClient} from './httpClient';//above snippet

function httpClientFactory(xhrBackend: XHRBackend, requestOptions: RequestOptions): Http {
  return new HttpClient(xhrBackend, requestOptions);
}

@NgModule({
  imports:[
    FormsModule,
    BrowserModule,
  ],
  declarations: APP_DECLARATIONS,
  bootstrap:[AppComponent],
  providers:[
     { provide: Http, useFactory: httpClientFactory, deps: [XHRBackend, RequestOptions]}
  ],
})
export class AppModule {
  constructor(){

  }
}

现在我不需要声明每个Http方法,可以在整个应用程序中正常使用Http。

我设置头的最大问题(在2022年)是HttpHeaders上的append方法返回原始对象的克隆,而没有修改原始对象本身。所以标题。Append ('header', 'value')不够。我必须重新分配结果或直接在HTTP调用中使用它:

let headers = new HttpHeaders();
headers = headers.append('header', 'value');
this.http.get<any>('https://someulr.com/api/users', { headers });

从Angular 4.3开始,HTTP拦截器现在可以通过新的HttpClient @angular/common/ HTTP使用了。X版本及更高版本。

现在为每个请求添加头文件非常简单:

import {
  HttpEvent,
  HttpInterceptor,
  HttpHandler,
  HttpRequest,
} from '@angular/common/http';
import { Observable } from 'rxjs';
import { Injectable } from '@angular/core';

@Injectable()
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);
  }
}

有一个不可变性的原则,这就是为什么在设置新内容之前需要克隆请求。

由于编辑头部是一个非常常见的任务,实际上有一个快捷方式(在克隆请求时):

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

创建拦截器之后,你应该使用HTTP_INTERCEPTORS提供的方法注册它。

import { HTTP_INTERCEPTORS } from '@angular/common/http';

@NgModule({
  providers: [{
    provide: HTTP_INTERCEPTORS,
    useClass: AddHeaderInterceptor,
    multi: true,
  }],
})
export class AppModule {}