[angular] Angular-모든 요청에 ​​대한 헤더 설정

이후의 모든 요청에 ​​대해 사용자가 로그인 한 후 일부 권한 부여 헤더를 설정해야합니다.


특정 요청에 대한 헤더를 설정하려면

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

참고

그러나 이러한 방식으로 모든 요청에 ​​대해 요청 헤더를 수동으로 설정하는 것은 불가능합니다.

사용자가 로그인 한 후 헤더 설정을 설정하고 로그 아웃시 해당 헤더를 제거하려면 어떻게합니까?



답변

대답하기 위해 HttpAngular 에서 원본 객체 를 래핑하는 서비스를 제공 할 수 있습니다 . 아래에 설명 된 것과 같은 것.

import {Injectable} from '@angular/core';
import {Http, Headers} from '@angular/http';

@Injectable()
export class HttpClient {

  constructor(private http: Http) {}

  createAuthorizationHeader(headers: Headers) {
    headers.append('Authorization', 'Basic ' +
      btoa('username:password'));
  }

  get(url) {
    let headers = new Headers();
    this.createAuthorizationHeader(headers);
    return this.http.get(url, {
      headers: headers
    });
  }

  post(url, data) {
    let headers = new Headers();
    this.createAuthorizationHeader(headers);
    return this.http.post(url, data, {
      headers: headers
    });
  }
}

그리고 Http물체를 주입하는 대신 이것을 주입 할 수 있습니다 ( HttpClient).

import { HttpClient } from './http-client';

export class MyComponent {
  // Notice we inject "our" HttpClient here, naming it Http so it's easier
  constructor(http: HttpClient) {
    this.http = httpClient;
  }

  handleSomething() {
    this.http.post(url, data).subscribe(result => {
        // console.log( result );
    });
  }
}

또한 Http클래스를 확장하여 자신 의 클래스를 제공하여 클래스에 다중 공급자를 사용하여 무언가를 수행 할 수 있다고 생각합니다 Http…이 링크를 참조하십시오 : http://blog.thoughtram.io/angular2/2015/11/23/multi-providers -in-angular-2.html .


답변

HTTP 인터셉터는 사용할 새로운 통해 HttpClient에서 @angular/common/http, 각도 4.3.x에서 버전 이후의 등 .

모든 요청에 ​​대해 헤더를 추가하는 것은 매우 간단합니다.

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.set('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 {}


답변

BaseRequestOptions이 시나리오에서는 확장 이 큰 도움이 될 수 있습니다. 다음 코드를 확인하십시오.

import {provide} from 'angular2/core';
import {bootstrap} from 'angular2/platform/browser';
import {HTTP_PROVIDERS, Headers, Http, BaseRequestOptions} from 'angular2/http';

import {AppCmp} from './components/app/app';


class MyRequestOptions extends BaseRequestOptions {
  constructor () {
    super();
    this.headers.append('My-Custom-Header','MyCustomHeaderValue');
  }
}

bootstrap(AppCmp, [
  ROUTER_PROVIDERS,
  HTTP_PROVIDERS,
  provide(RequestOptions, { useClass: MyRequestOptions })
]);

모든 통화에 ‘내 맞춤 헤더’가 포함되어야합니다.

최신 정보:

위 코드 대신 언제든지 헤더를 변경할 수 있도록 다음 코드를 사용하여 새 헤더를 추가 할 수도 있습니다.

this.http._defaultOptions.headers.append('Authorization', 'token');

당신이 할 수있는 삭제

this.http._defaultOptions.headers.delete('Authorization');

또한 값을 설정하는 데 사용할 수있는 다른 기능이 있습니다.

this.http._defaultOptions.headers.set('Authorization', 'token');

위의 솔루션은 여전히 ​​타자기 컨텍스트에서 완전히 유효하지 않습니다. _defaultHeaders는 보호되어 있으며 이와 같이 사용해서는 안됩니다. 빠른 수정을 위해 위의 솔루션을 권장하지만 오랫동안 인증을 처리하는 http 호출 주위에 자신의 래퍼를 작성하는 것이 좋습니다. 더 좋고 깨끗한 auth0의 다음 예제를 보자.

https://github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts

업데이트-2018 년 6 월
많은 사람들 이이 솔루션을 사용하는 것을 보았지만 그렇지 않으면 조언 할 것입니다. 전 세계에 헤더를 추가하면 앱에서 나가는 모든 API 호출에 인증 토큰이 전송 됩니다. 따라서 인터콤이나 zendesk 또는 다른 API와 같은 타사 플러그인으로가는 API 호출에도 승인 헤더가 있습니다. 이로 인해 큰 보안 결함이 발생할 수 있습니다. 대신 인터셉터를 전역 적으로 사용하지만 발신 전화가 서버의 API 끝점을 향하는 지 여부를 수동으로 확인한 다음 인증 헤더를 첨부하십시오.


답변

답변이 늦었지만 다른 사람에게 도움이 될 수 있습니다. @NgModule사용될 때 모든 요청에 ​​헤더를 삽입하려면 다음을 수행하십시오.

(Angular 2.0.1에서 이것을 테스트했습니다)

/**
 * Extending BaseRequestOptions to inject common headers to all requests.
 */
class CustomRequestOptions extends BaseRequestOptions {
    constructor() {
        super();
        this.headers.append('Authorization', 'my-token');
        this.headers.append('foo', 'bar');
    }
}

이제 @NgModule다음 을 수행하십시오.

@NgModule({
    declarations: [FooComponent],
    imports     : [

        // Angular modules
        BrowserModule,
        HttpModule,         // This is required

        /* other modules */
    ],
    providers   : [
        {provide: LocationStrategy, useClass: HashLocationStrategy},
        // This is the main part. We are telling Angular to provide an instance of
        // CustomRequestOptions whenever someone injects RequestOptions
        {provide: RequestOptions, useClass: CustomRequestOptions}
    ],
    bootstrap   : [AppComponent]
})


답변

에서 Angular 2.1.2내가 확장하여이 접근 각도 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)
  }
}

그런 다음 내 App Providers에서 커스텀 팩토리를 사용하여 ‘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응용 프로그램 전체에서 정상적으로 사용할 수 있습니다 .


답변

Angular 2 HttpProvider 를 확장하여 사용자 정의 Http 클래스를 작성하고 사용자 정의 Http 클래스 에서 constructorand request메소드를 대체하십시오 . 아래 예제 Authorization는 모든 http 요청에 헤더를 추가합니다 .

import {Injectable} from '@angular/core';
import {Http, XHRBackend, RequestOptions, Request, RequestOptionsArgs, Response, Headers} from '@angular/http';
import {Observable} from 'rxjs/Observable';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/catch';

@Injectable()
export class HttpService extends Http {

  constructor (backend: XHRBackend, options: RequestOptions) {
    let token = localStorage.getItem('auth_token'); // your custom token getter function here
    options.headers.set('Authorization', `Bearer ${token}`);
    super(backend, options);
  }

  request(url: string|Request, options?: RequestOptionsArgs): Observable<Response> {
    let token = localStorage.getItem('auth_token');
    if (typeof url === 'string') { // meaning we have to add the token to the options, not in url
      if (!options) {
        // let's make option object
        options = {headers: new Headers()};
      }
      options.headers.set('Authorization', `Bearer ${token}`);
    } else {
    // we have to add the token to the url object
      url.headers.set('Authorization', `Bearer ${token}`);
    }
    return super.request(url, options).catch(this.catchAuthError(this));
  }

  private catchAuthError (self: HttpService) {
    // we have to pass HttpService's own instance here as `self`
    return (res: Response) => {
      console.log(res);
      if (res.status === 401 || res.status === 403) {
        // if not authenticated
        console.log(res);
      }
      return Observable.throw(res);
    };
  }
}

그런 다음 주요 구성 app.module.ts를 제공 할 수 XHRBackend는 AS ConnectionBackend공급자 및 RequestOptions사용자 지정 HTTP 클래스 :

import { HttpModule, RequestOptions, XHRBackend } from '@angular/http';
import { HttpService } from './services/http.service';
...
@NgModule({
  imports: [..],
  providers: [
    {
      provide: HttpService,
      useFactory: (backend: XHRBackend, options: RequestOptions) => {
        return new HttpService(backend, options);
      },
      deps: [XHRBackend, RequestOptions]
    }
  ],
  bootstrap: [ AppComponent ]
})

그런 다음 서비스에서 사용자 정의 http 제공자를 사용할 수 있습니다. 예를 들면 다음과 같습니다.

import { Injectable }     from '@angular/core';
import {HttpService} from './http.service';

@Injectable()
class UserService {
  constructor (private http: HttpService) {}

  // token will added automatically to get request header
  getUser (id: number) {
    return this.http.get(`/users/${id}`).map((res) => {
      return res.json();
    } );
  }
}

다음은 포괄적 인 가이드입니다 -http : //adonespitogo.com/articles/angular-2-extending-http-provider/


답변

Angular 5 이상에서는 요청 및 응답 작업을 일반화하기 위해 HttpInterceptor를 사용할 수 있습니다. 이를 통해 중복을 피할 수 있습니다.

1) 공통 헤더

2) 응답 타입 지정

3) 질의 요청

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

@Injectable()
export class AuthHttpInterceptor implements HttpInterceptor {

  requestCounter: number = 0;
  constructor() {
  }

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

    request = request.clone({
      responseType: 'json',
      setHeaders: {
        Authorization: `Bearer token_value`,
        'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'
      }
    });

    return next.handle(request).do((event: HttpEvent<any>) => {
      if (event instanceof HttpResponse) {
        // do stuff with response if you want
      }
    }, (err: any) => {
      if (err instanceof HttpErrorResponse) {
        // do stuff with response error if you want
      }
    });
  }
}

이 AuthHttpInterceptor 클래스를 HttpInterceptors의 공급자로 사용할 수 있습니다.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { AppRoutingModule } from './app.routing-module';
import { AuthHttpInterceptor } from './services/auth-http.interceptor';
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule,
    BrowserAnimationsModule,
  ],
  providers: [
    {
      provide: HTTP_INTERCEPTORS,
      useClass: AuthHttpInterceptor,
      multi: true
    }
  ],
  exports: [],
  bootstrap: [AppComponent]
})
export class AppModule {
}