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


334

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


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

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

참고

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

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



답변:


379

대답하기 위해 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 .


1
'this.http = http;'는 어디에 있습니까? 에서 나왔습니다. 사용하기 전에 선언해야한다고 생각하십니까?
co2f2e 2016 년

1
앵귤러 헤더 (설정 및 추가 기능)는 헤더 키를 "정규화"하고 소문자로 만듭니다. Headers.d.ts에서 : // "HTTP 문자 세트는 대소 문자를 구분하지 않는 토큰으로 식별됩니다."// spec. tools.ietf.org/html/rfc2616의 스펙 스펙에서 작동하는 백엔드가없는 사용자의 경우; 우회가 있습니다 : let headersMap = .get (options, ' headers._headersMap ', new Map ()); headersMap.set ( '인가'[ .replace ( Bearer ${token}/ \ "/ g '')])
sangress

@DiegoUnanue Angular 2의 최종 버전을 사용하고 있으며 Thierry의 구현 작업이 있습니다. import 문에서 'angular2'를 '@angular'로 바꾸십시오.
f123

Mark Pieszak- HttpClient의 공급자를 포함시켜야합니까?
user3127109

이제 TS는 오류를 던진다.` '{헤더의 인수 : 헤더; } ''RequestOptionsArgs '유형의 매개 변수에 지정할 수 없습니다.
elporfirio

142

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 {}

나는 이것을 구현하고 ng serve를 할 때 요청 헤더를 볼 수 있지만 ng b prod를 수행하고 tomcat 내부에 배포 할 때 스프링 부트를 사용하여 헤더를 볼 수 없습니다. 헤더는 어디로 갔습니까?
naoru

1
Express 노드 API로 작업하고 있기 때문에인지 모르지만 공식 Angular 문서에서도 작동하지 않습니다. : /
Maxime Lafarie

오류 TypeError : 개체가 아닌 개체에서 CreateListFromArrayLike가 호출 됨
DAG

1
HttpInterceptor에 어떤 것을 주입 하시겠습니까?
zaitsman

나는 이것을 똑같이 구현했지만 PUT 및 DELETE API 요청 헤더에서 작동하지 않습니다.
Pooja

78

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 끝점을 향하는 지 여부를 수동으로 확인한 다음 인증 헤더를 첨부하십시오.


1
this.http._defaultOptions.headers.delete ( 'My-Custom-Header') 따라서 다음 코드를 통해 위의 프로세스를 줄일 수 있습니다 .http._defaultOptions.headers.append ( 'My-New-Custom-Header', 'newvalue ')
anit

2
@ 디니 스트로 네, 이제 나는 이것을하지 않는 것이 좋습니다. 각도 베타 제한과 전 세계적으로 인증 흐름을 제어하는 ​​습관 때문에이 해결 방법을 생각해 내야했습니다. 그러나 지금은 github.com/auth0/angular2-jwt/blob/master/angular2-jwt.ts 에 더 좋고 깨끗한 솔루션이 있다고 생각합니다 .
anit

1
BaseRequestOptions 사용의 문제점은 생성자가 브라우저에서 애플리케이션 수명 동안 한 번만 실행된다는 것입니다. 따라서 시간 동안 헤더 값을 변경하려면 (예 : csrf_token)이 방법으로 수행 할 수 없습니다 (이 클래스에서 병합 메소드를 재정의해도 도움이되지 않음 :()
Kamil Kiełczewski

1
문제점은 HTTP에 직접 액세스하는 랩퍼 써드 파티 라이브러리를 사용하는 경우이를 사용하기 위해 다시 작성해야한다는 것입니다. 나는 아직도 그 문제를 해결하는 방법을 모른다. 인터셉터가 실제로 필요합니다. 누구든지 더 나은 방법을 알고 있는지 확실하지 않습니다.
Piotr Stulinski 16:12의

6
안녕하세요, angular4 _defaultOptions에서 보호되어 서비스에서 호출 할 수 없습니다
Andurit

24

답변이 늦었지만 다른 사람에게 도움이 될 수 있습니다. @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]
})

4
@Injectable이 필요하고 클래스에서 헤더를 정의하면 @Injectable ()에 의해 테스트되었습니다. export class CustomRequestOptions extends BaseRequestOptions {headers : Headers = new Headers ({ 'Authorization': 'xxx'}); }
EasonBlack

글쎄, 나는 이것을 2.0.0에서했고, 2.0.1을 체크하지 않았다
EasonBlack

여기서 중요한 참고 사항 CustomRequestOptions@ Inject / @ Injectable을 사용할 때도 아무것도 주입 할 수없는 문제가 발생했습니다 . 내가 깨달은 솔루션은 확장하는 RequestOptions것이 아니라 확장하는 것이 었습니다 BaseRequestOptions. 제공하는 BaseRequestOptions것은 효과가 없지만 RequestOptions대신 확장 하면 DI가 다시 작동합니다.
의회

5
이 솔루션은 간단하지만 사용자가 로그 아웃했다가 다시 로그인하고 토큰이 변경 Authorization되면 헤더는 응용 프로그램 초기화시 한 번만 설정 되므로 더 이상 작동하지 않습니다 .
Alex Paramonov

예, @AlexeyVParamonov를 수정하십시오. 토큰이 한 번 설정된 경우에만 유용합니다. 그렇지 않으면 우리는 당신이 말한 것처럼 사건에 대한 인터셉터를 작성합니다.
Shashank Agrawal

15

에서 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응용 프로그램 전체에서 정상적으로 사용할 수 있습니다 .


이 답변은 API 서버에서 URL을 필터링하고 호출에 인증 토큰 만 추가 할 수 있었기 때문에 나에게 가장 효과적이었습니다. 요청을 다음과 같이 변경했습니다. request (url : string | Request, options ?: RequestOptionsArgs) : Observable <Response> {var _url : string = url.toString (); if (_url.indexOf ( 'api.myserver.com')> -1) {옵션 = this._setCustomHeaders (옵션); } return super.request (url, options)}
Chris Holcomb

필자의 경우 withCredentials 및 Headers는 요청 메소드의 url 매개 변수에서 가져 왔습니다. 다음과 같이 코드를 변경했습니다. request (url : string | Request, options ?: RequestOptionsArgs) : Observable <Response> {options = this._setCustomHeaders (options); if (typeof (url) === "object") {(<Request> url) .withCredentials = 옵션 .withCredentials; (<Request> url) .headers = 옵션 .headers; } return super.request (url, options)}
Argnist

request()당신이 오버로드하는 방법은 두 호출 서명을 가지고 있으며, options경우 속성은 사용되는 url문자열로 지정했습니다. 경우 url의 인스턴스 인 Requestoptions특성은 무시됩니다. 이로 인해 오류를 잡기가 어려울 수 있습니다. 자세한 내용은 내 답변을 참조하십시오.
Slava Fomin II


이것은 각도 4.2까지 나를 위해 일했습니다. 4.3 인터셉터가 있습니다.
cabaji99

12

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/


이 방법은 대체 클래스 공급자를 사용하는 데 적합합니다. 모듈에서와 같이 "provide : HttpService"대신 "provide : Http"를 사용하면 일반적으로 Http를 사용할 수 있습니다.
길버트 아레나스 대거

이 확장 http 클래스에 추가 속성을 추가하려면 어떻게해야합니까? 예를 들어, router : 라우터 또는 모든 사용자 정의 주사 가능 서비스.
shafeequemat

@shafeequemat 당신은 이것을 사용하여 그것을 할 수 없습니다. 사용자 정의 http 클래스에서 다른 메소드를 정의 할 수 있습니다 (예 :) setRouter(router). 또는 다른 클래스를 작성하고 반대쪽에 사용자 정의 http 클래스를 삽입 할 수 있습니다.
Adones Pitogo

9

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 {
}

8

결코 늦지 않는 것보다 낫다 ... =)

확장 개념 BaseRequestOptions(여기에서 https://angular.io/docs/ts/latest/guide/server-communication.html#!#override-default-request-options )을 취하고 헤더를 "새로"새로 고칠 수 있습니다. "(생성자뿐만 아니라). 다음과 같이 getter / setter "headers"속성 재정의를 사용할 수 있습니다.

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

@Injectable()
export class DefaultRequestOptions extends BaseRequestOptions {

    private superHeaders: Headers;

    get headers() {
        // Set the default 'Content-Type' header
        this.superHeaders.set('Content-Type', 'application/json');

        const token = localStorage.getItem('authToken');
        if(token) {
            this.superHeaders.set('Authorization', `Bearer ${token}`);
        } else {
            this.superHeaders.delete('Authorization');
        }
        return this.superHeaders;
    }

    set headers(headers: Headers) {
        this.superHeaders = headers;
    }

    constructor() {
        super();
    }
}

export const requestOptionsProvider = { provide: RequestOptions, useClass: DefaultRequestOptions };

약간의 업데이트 : 더 나은 성능을 위해 모든 정적 헤더 (예 : 'Content-Type')를 생성자로 옮기는 것을 고려할 수 있습니다.
Александр Ильинский

7

이것은 모든 요청에 ​​대해 토큰을 설정하는 방법입니다.

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

그리고 app.module.ts에 등록하십시오

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule
    ],
    providers: [
        { provide: RequestOptions, useClass: CustomRequestOptions }
    ],
    bootstrap: [AppComponent]
})
export class AppModule { }

6

다음은 Angular2 final 용으로 업데이트 된 허용 된 답변 버전입니다.

import {Injectable} from "@angular/core";
import {Http, Headers, Response, Request, BaseRequestOptions, RequestMethod} from "@angular/http";
import {I18nService} from "../lang-picker/i18n.service";
import {Observable} from "rxjs";
@Injectable()
export class HttpClient {

    constructor(private http: Http, private i18n: I18nService ) {}

    get(url:string):Observable<Response> {
        return this.request(url, RequestMethod.Get);
    }

    post(url:string, body:any) {   
        return this.request(url, RequestMethod.Post, body);
    }

    private request(url:string, method:RequestMethod, body?:any):Observable<Response>{

        let headers = new Headers();
        this.createAcceptLanguageHeader(headers);

        let options = new BaseRequestOptions();
        options.headers = headers;
        options.url = url;
        options.method = method;
        options.body = body;
        options.withCredentials = true;

        let request = new Request(options);

        return this.http.request(request);
    }

    // set the accept-language header using the value from i18n service that holds the language currently selected by the user
    private createAcceptLanguageHeader(headers:Headers) {

        headers.append('Accept-Language', this.i18n.getCurrentLang());
    }
}

물론 그것은 같은 방법을 연장해야 delete하고 put필요한 경우 (나는 내 프로젝트에서이 시점에서 아직 필요하지 않습니다).

장점은 get/ post/ ... 메소드 에 중복 코드가 적다는 것입니다 .

필자의 경우 인증을 위해 쿠키를 사용합니다. Accept-LanguageAPI에서 반환 한 많은 값이 사용자의 언어로 번역되어 있기 때문에 i18n의 헤더 ( 헤더)가 필요했습니다 . 내 응용 프로그램에서 i18n 서비스는 사용자가 현재 선택한 언어를 보유합니다.


tslint가 어떻게 헤더를 무시하도록합니까?
Winnemucca

5

다음과 같이 별도의 서비스를 유지하는 방법

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


            @Injectable()
            export class HttpClientService extends RequestOptions {

                constructor(private requestOptionArgs:RequestOptions) {
                    super();     
                }

                addHeader(headerName: string, headerValue: string ){
                    (this.requestOptionArgs.headers as Headers).set(headerName, headerValue);
                }
            }

다른 장소에서 이것을 호출하면 this.httpClientService.addHeader("Authorization", "Bearer " + this.tok);

당신은 추가 헤더의 예를 볼 수 있습니다 : - 인증은 다음과 같이

여기에 이미지 설명을 입력하십시오


5

조사를 마친 후 최종적이고 가장 쉬운 방법은 BaseRequestOptions내가 선호하는 것을 확장 하는 것입니다.
다음은 어떤 이유로 시도하고 포기하는 방법입니다.
1.에서 확장 BaseRequestOptions하고 동적 헤더를 추가하십시오 constructor(). 로그인하면 작동하지 않습니다. 한 번 생성됩니다. 따라서 역동적이지 않습니다.
2. 연장하십시오 Http. 위와 같은 이유로에에 동적 헤더를 추가 할 수 없습니다 constructor(). 그리고 request(..)메소드를 다시 작성 하고 헤더를 다음과 같이 설정하면 :

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

이 메소드를 덮어 써야하지만 모든 get / post / put 메소드는 아닙니다.

3. 그리고 내가 선호하는 솔루션은 확장 BaseRequestOptions및 덮어 쓰기입니다 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;
 }
}

merge()함수는 모든 요청에 ​​대해 호출됩니다.


주어진 모든 답변 중, 이것은 이미 확장 기반의 솔루션을 찾은 이후로주의를 기울인 답변입니다 BaseRequestOptions. 그러나 슬프게도 이것은 나를 위해 작동하지 않았습니다. 가능한 이유가 있습니까?
vigamage

작동했습니다. 이 솔루션은 문제가 없으며 서버에 문제가 있습니다. CORS 프리 플라이트 요청에 대해 일부 구성을 수행해야했습니다. 이 링크를 참조하십시오 stackoverflow.com/a/43962690/3892439
vigamage

AuthRequestOptions앱의 나머지 부분에 어떻게 연결 합니까? 나는 이것을 providers섹션 에 넣으려고했지만 아무것도하지 않았다.
트래비스 파크

에 대한 공급자를 재정의 RequestOptions하지 않아야 BaseRequestOptions합니다. angular.io/api/http/BaseRequestOptions
트래비스 파크

내 응용 프로그램에서는 BaseRequestOptions를 확장하고 이미 RequestOptions를 확장합니다. 그런 다음 app.module에서 제공자를 설정해야합니다.{ provide: RequestOptions, useClass: AuthRequestOptions }
Mavlarn

5

비록 매우 늦게 대답하고 있지만 누군가가 더 쉬운 해결책을 찾고 있다면.

angular2-jwt를 사용할 수 있습니다. angular2-jwt는 Angular 2 앱에서 HTTP 요청을 할 때 JSON 웹 토큰 (JWT)을 Authorization 헤더로 자동 첨부하는 데 유용합니다.

고급 구성 옵션으로 글로벌 헤더를 설정할 수 있습니다

export function authHttpServiceFactory(http: Http, options: RequestOptions) {
  return new AuthHttp(new AuthConfig({
    tokenName: 'token',
        tokenGetter: (() => sessionStorage.getItem('token')),
        globalHeaders: [{'Content-Type':'application/json'}],
    }), http, options);
}

그리고 요청 토큰 당 전송

    getThing() {
  let myHeader = new Headers();
  myHeader.append('Content-Type', 'application/json');

  this.authHttp.get('http://example.com/api/thing', { headers: myHeader })
    .subscribe(
      data => this.thing = data,
      err => console.log(error),
      () => console.log('Request Complete')
    );

  // Pass it after the body in a POST request
  this.authHttp.post('http://example.com/api/thing', 'post body', { headers: myHeader })
    .subscribe(
      data => this.thing = data,
      err => console.log(error),
      () => console.log('Request Complete')
    );
}

고토에 도움이 될 것 github.com/auth0/angular2-jwt#installation 과 설치 안내서를 사용하여이 대답을 적용
Zuriel

4

나는 기본 옵션을 재정의하는 아이디어를 좋아합니다. 이것은 좋은 해결책처럼 보입니다.

그러나 Http수업 을 확장해야하는 경우 . 이 내용을 반드시 읽어보십시오!

여기에있는 일부 답변은 실제로 request()메서드 오버로드가 잘못 표시 되어 포착하기 어려운 오류와 이상한 동작을 유발할 수 있습니다. 나는 이것을 스스로 우연히 발견했다.

이 솔루션은 request()Angular의 메소드 구현을 기반으로 4.2.x하지만 향후 호환 가능해야합니다.

import {Observable} from 'rxjs/Observable';
import {Injectable} from '@angular/core';

import {
  ConnectionBackend, Headers,
  Http as NgHttp,
  Request,
  RequestOptions,
  RequestOptionsArgs,
  Response,
  XHRBackend
} from '@angular/http';


import {AuthenticationStateService} from '../authentication/authentication-state.service';


@Injectable()
export class Http extends NgHttp {

  constructor (
    backend: ConnectionBackend,
    defaultOptions: RequestOptions,
    private authenticationStateService: AuthenticationStateService
  ) {
    super(backend, defaultOptions);
  }


  request (url: string | Request, options?: RequestOptionsArgs): Observable<Response> {

    if ('string' === typeof url) {

      url = this.rewriteUrl(url);
      options = (options || new RequestOptions());
      options.headers = this.updateHeaders(options.headers);

      return super.request(url, options);

    } else if (url instanceof Request) {

      const request = url;
      request.url = this.rewriteUrl(request.url);
      request.headers = this.updateHeaders(request.headers);

      return super.request(request);

    } else {
      throw new Error('First argument must be a url string or Request instance');
    }

  }


  private rewriteUrl (url: string) {
    return environment.backendBaseUrl + url;
  }

  private updateHeaders (headers?: Headers) {

    headers = headers || new Headers();

    // Authenticating the request.
    if (this.authenticationStateService.isAuthenticated() && !headers.has('Authorization')) {
      headers.append('Authorization', 'Bearer ' + this.authenticationStateService.getToken());
    }

    return headers;

  }

}

import { Http as NgHttp } from '@angular/http';이름 충돌을 방지하기 위해 원래 클래스를 이런 방식으로 가져 옵니다.

여기서 해결되는 문제는 request()메소드에 두 가지 다른 호출 서명이 있다는 것입니다. RequestURL 대신 object가 전달 되면 Angular string에서 options인수를 무시합니다. 따라서 두 경우 모두 올바르게 처리해야합니다.

그리고이 재정의 된 클래스를 DI 컨테이너에 등록하는 방법의 예는 다음과 같습니다.

export const httpProvider = {
  provide: NgHttp,
  useFactory: httpFactory,
  deps: [XHRBackend, RequestOptions, AuthenticationStateService]
};


export function httpFactory (
  xhrBackend: XHRBackend,
  requestOptions: RequestOptions,
  authenticationStateService: AuthenticationStateService
): Http {
  return new Http(
    xhrBackend,
    requestOptions,
    authenticationStateService
  );
}

이러한 접근 방식으로 주사 할 수 있습니다 Http 클래스를 정상적으로 있지만 재정의 된 클래스는 대신 마법으로 주입됩니다. 이를 통해 응용 프로그램의 다른 부분을 변경하지 않고도 솔루션을 쉽게 통합 할 수 있습니다 (다형성).

모듈 메타 데이터 httpProviderproviders속성에 추가 하십시오.


1

가장 간단한

config.ts파일 만들기

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

export class Config {
    url: string = 'http://localhost:3000';
    httpOptions: any = {
        headers: new HttpHeaders({
           'Content-Type': 'application/json',
           'Authorization': JSON.parse(localStorage.getItem('currentUser')).token
        })
    }
}

그런 다음 파일을 service가져 오십시오.config.ts

import { Config } from '../config';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class OrganizationService {
  config = new Config;

  constructor(
    private http: HttpClient
  ) { }

  addData(data): Observable<any> {
     let sendAddLink = `${this.config.url}/api/addData`;

     return this.http.post(sendAddLink , data, this.config.httpOptions).pipe(
       tap(snap => {
      return snap;
        })
    );
 } 

나는 그것이 가장 단순하고 안전한 것이라고 생각합니다.


0

각도 2.0.1 이상에 대한 변경 사항이 있습니다.

    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 { }

작동하지 않으면 직접 시도하십시오. 새로 고침 외에는 아무 것도 호출되지 않습니다.
Phil

0

간단한 솔루션을 선택할 수 있습니다.> api get (또는 다른) 기능에 의해 기본값 옵션 병합 또는로드에 새 헤더 추가.

get(endpoint: string, params?: any, options?: RequestOptions) {
  if (!options) {
    options = new RequestOptions();
    options.headers = new Headers( { "Accept": "application/json" } ); <<<<
  }
  // [...] 
}

물론이 헤더를 기본 옵션 또는 클래스 내에서 외부화 할 수 있습니다. 이것은 이온 생성 api.ts @Injectable () 내보내기 클래스 API {}에 있습니다.

매우 빠르며 나를 위해 일합니다. json / ld 형식을 원하지 않았습니다.


-4

다음 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 에서 가져옴

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.