Angular-すべてのリクエストにヘッダーを設定します


334

ユーザーがログインした後、後続のすべてのリクエストに対していくつかのAuthorizationヘッダーを設定する必要があります。


特定のリクエストにヘッダーを設定するには、

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

参照

ただし、この方法ですべての要求に要求ヘッダーを手動で設定することはできません。

ユーザーがログインしたらヘッダーを設定し、ログアウト時にそれらのヘッダーを削除するにはどうすればよいですか?



回答:


378

回答するには、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
角型ヘッダー(セットおよび追加機能)は、ヘッダーのキーを「正規化」して小文字にします。From Headers.d.ts://「大文字と小文字を区別しないトークンによってHTTP文字セットが識別される」// tools.ietf.org/html/rfc2616の仕様仕様で機能 するバックエンドがない人向け。これがバイパスです:let headersMap = .get(options、 'headers._headersMap'、new Map()); headersMap.set( 'Authorization'、[. replace(Bearer ${token}、/ \ "/ g、 '')]);
sangress

@DiegoUnanue Angular 2の最終バージョンを使用しており、Thierryの実装が機能しています。importステートメントで「angular2」を「@angular」に置き換えるだけです。
f123 2016年

Mark Pieszak-HttpClientのプロバイダーを含める必要がありますか?
user3127109 2016

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内にデプロイすると、ヘッダーが表示されません... spring-bootを使用して、ヘッダーはどこに行きましたか?
naoru 2017

1
ExpressノードAPIを使用しているためかどうかはわかりませんが、公式のAngularドキュメントを使用しても機能しません。:/
Maxime Lafarie 2017

エラーTypeError:CreateListFromArrayLikeが非オブジェクトで呼び出されました
DAG

1
どのようにしてHttpInterceptorに何かを注入しますか?
zaitsman 2017年

私はこれと同じことを実装しましたが、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 })
]);

これには、すべての呼び出しで「My-Custom-Header」が含まれる必要があります。

更新:

上記のコードの代わりにいつでもヘッダーを変更できるようにするには、次のコードを使用して新しいヘッダーを追加することもできます。

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

削除することができます

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

また、値を設定するために使用できる別の関数もあります。

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

上記の解決策は、typescriptのコンテキストではまだ完全に有効ではありません。_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')したがって、上記のプロセスは、コードthis.http._defaultOptions.headers.append( 'My-New-Custom-Header'、 'newvalue ')
anit

2
@Dinistroはい、今私は自分でこれを行うことをお勧めしません。角度ベータ版の制限と、認証フローをグローバルに制御する私の習慣のため、この回避策を考え出す必要がありました。しかし、私は今のところgithub.com/auth0/angular2-jwt/blob/master/angular2-jwt.tsがより優れたクリーンなソリューションを持っていると信じています。
anit 2016年

1
BaseRequestOptionsを使用する際の問題は、そのコンストラクターがブラウザーのアプリケーションの存続期間に1回だけ実行されることです。したがって、時間中にヘッダー値を変更する場合(例:csrf_token)、この方法で変更することはできません(このクラスのマージメソッドをオーバーライドしても
役に立た

1
問題は、ラッパーを使用する場合、HTTPに直接アクセスするサードパーティライブラリを使用するには、HTTPを書き直す必要があることです。私はまだそれを回避する方法を知りません。インターセプターは本当に必要です。誰かがより良い方法を知っているかどうかわかりません。
Piotr Stulinski 2016

6
こんにちは、angular4 _defaultOptionsは保護されているため、サービスから
呼び出せ

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()でテストしました。エクスポートクラスCustomRequestOptions extends BaseRequestOptions {headers:Headers = new Headers({'Authorization': 'xxx'}); }
EasonBlack 2016年

まあ、私はこれを2.0.0で行い、2.0.1をチェックしませんでした
EasonBlack

ここでの重要な注意は、CustomRequestOptions@ Inject / @ Injectableを使用しているときにも何も注入できないという問題に遭遇しました。私が実現した解決策は、拡張RequestOptionsではなく拡張することでしたBaseRequestOptions。提供してBaseRequestOptionsも機能しませんが、拡張RequestOptionsするとDIが再び機能します。
議会

5
このソリューションは簡単ですが、ユーザーがログアウトして再度ログインすると、トークンが変更Authorizationされます。アプリケーションの初期化時にヘッダーが1回しか設定されないため、機能しなくなります。
Alex Paramonov 2016年

はい、@ AlexeyVParamonovを修正します。これは、トークンが一度設定されている場合にのみ役立ちます。それ以外の場合は、あなたが言ったようにケースのインターセプターを作成します。
Shashank Agrawal 2016年

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

次に、私のアプリプロバイダーで、カスタムファクトリを使用して「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){options = this._setCustomHeaders(options); } return super.request(url、options)}
Chris Holcomb

私の場合、withCredentialsとヘッダーは、リクエストメソッドのurlパラメータから取得されました。次のようにコードを変更しました:request(url:string | Request、options ?: RequestOptionsArgs):Observable <Response> {options = this._setCustomHeaders(options); if(typeof(url)=== "object"){(<Request> url).withCredentials = options.withCredentials; (<Request> url).headers = options.headers; } return super.request(url、options)}
Argnist

request()あなたがオーバーロードしている方法は、2つのコールのシグネチャがあり、optionsときに、プロパティにのみ使用されるurl文字列として指定します。場合urlのインスタンスをされRequestoptionsプロパティは単に無視されます。これにより、エラーをキャッチすることが困難になる可能性があります。詳細については、私の回答をご覧ください。
Slava Fomin II 2017

このソリューションにはサーバープラットフォームに関するいくつかの問題があることに注意してください。ただしこれを回避するための回避策があります。
Alireza Mirian 2017

これは、angular 4.2まで機能しました。4.3インターセプターがあります。
cabaji99

12

Angular 2 Httpプロバイダーを拡張してカスタムHttpクラスを作成し、カスタムHttpクラスのconstructorおよび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);
    };
  }
}

次に、をプロバイダーとして、をカスタムHttpクラスapp.module.tsに提供するようにメインを構成します。XHRBackendConnectionBackendRequestOptions

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を操作できます。
Gilbert Arenas Dagger

この拡張httpクラスにプロパティを追加するにはどうすればよいですか?たとえば、ルーター:ルーターまたは任意のカスタム注入可能サービス。
shafeequemat 2017

@shafeequematこれを使ってそれを行うことはできません。たとえば、カスタムhttpクラスに別のメソッドを定義できますsetRouter(router)。または、別のクラスを作成して、反対の代わりにカスタムのhttpクラスを挿入することもできます。
Adones Pitogo 2018年

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 / ...メソッドの。

私の場合、認証にCookieを使用していることに注意してください。Accept-LanguageAPIから返される多くの値はユーザーの言語に翻訳されるため、i18nのヘッダー(ヘッダー)が必要でした。私のアプリでは、i18nサービスはユーザーが現在選択している言語を保持しています。


どのようにしてtslintにヘッダーを無視させるのですか?
Winnemucca 2017年

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セクションに入れてみましたが、何も起こりませんでした。
Travis Parks

プロバイダーをオーバーライドする必要があります RequestOptionsではなくBaseRequestOptionsangular.io/api/http/BaseRequestOptions
Travis Parks

私のアプリでは、BaseRequestOptionsを拡張するだけで、すでにRequestOptionsを拡張しています。その後app.moduleに、あなたは、プロバイダを設定する必要があります{ provide: RequestOptions, useClass: AuthRequestOptions }
Mavlarn

5

私はこれに非常に遅く答えていますが、誰かがより簡単な解決策を探しているなら。

angular2-jwtを使用できます。angular2-jwtは、Angular 2アプリからHTTPリクエストを行うときに、AuthorizationヘッダーとしてJSON Web Token(JWT)を自動的に添付するのに役立ちます。

高度な設定オプションでグローバルヘッダーを設定できます

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()メソッドに2つの異なる呼び出し署名があることです。ときにRequestオブジェクトが代わりにURLを渡されstringoptions引数は角度によって無視されます。したがって、両方のケースを適切に処理する必要があります。

そして、このオーバーライドされたクラスを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すると、クラスを通常どおり注入できますが、オーバーライドされたクラスは代わりに魔法のように注入されます。これにより、アプリケーションの他の部分(動作中の多態性)を変更することなく、ソリューションを簡単に統合できます。

モジュールのメタデータのプロパティに追加httpProviderするだけprovidersです。


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

次にserviceconfig.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

angular 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" } ); <<<<
  }
  // [...] 
}

もちろん、このヘッダーをデフォルトオプションまたはクラス内の何でも外部化できます。これは、Ionicで生成された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.