Подтвердить что ты не робот

Каков правильный способ использования angular2 http-запросов с защитой Django CSRF?

В Angular1 проблему можно решить, настроив $http-provider. Как:

app.config(function($httpProvider) {
  $httpProvider.defaults.xsrfCookieName = 'csrftoken';
  $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
});

Какая хорошая практика сделать то же самое в Angular2?

В Angular2 для работы с http-запросами нам нужно использовать класс Http. Конечно, это не очень хорошая практика для добавления CSRF-линии для каждого вызова постфункции.

Я предполагаю, что в Angular2 я должен создать собственный класс, который наследует класс Angular2 Http и переопределяет постфункцию. Это правильный подход или есть более элегантный метод?

4b9b3361

Ответ 1

Ответ Victor K совершенно справедлив, однако, как и для angular 2.0.0-rc.2, предпочтительным подходом было бы использовать CookieXSRFStrategy, как показано ниже,

bootstrap(AngularApp, [
  HTTP_PROVIDERS,
  provide(XSRFStrategy, {useValue: new CookieXSRFStrategy('csrftoken', 'X-CSRFToken')})
]);

Ответ 2

Теперь, когда освобождается Angular 2, кажется, что это правильный способ, используя CookieXSRFStrategy.

Я настроил мое приложение на основной модуль, но вы можете сделать то же самое в своем основном прикладном модуле:

import { ModuleWithProviders, NgModule, Optional, SkipSelf } from '@angular/core';
import { CommonModule }   from '@angular/common';
import { HttpModule, XSRFStrategy, CookieXSRFStrategy } from '@angular/http';

@NgModule({
    imports: [
        CommonModule,
        HttpModule
     ],
    declarations: [ ],
    exports: [ ],
    providers: [
        {
            provide: XSRFStrategy,
            useValue: new CookieXSRFStrategy('csrftoken', 'X-CSRFToken')
        }
    ]
})


export class CoreModule {
}, 

Ответ 3

Решение для Angular2 не так просто, как для углового 1. Вам нужно:

  • Выберите значение csrftoken cookie.

  • Добавьте это значение, чтобы запросить заголовки с именем X-CSRFToken.

Я предлагаю этот фрагмент:

import {Injectable, provide} from 'angular2/core';
import {BaseRequestOptions, RequestOptions} from 'angular2/http'

@Injectable()
export class ExRequestOptions extends BaseRequestOptions  {
  constructor() {
    super();
    this.headers.append('X-CSRFToken', this.getCookie('csrftoken'));
  }

  getCookie(name) {
    let value = "; " + document.cookie;
    let parts = value.split("; " + name + "=");
    if (parts.length == 2) 
      return parts.pop().split(";").shift();
  }
}

export var app = bootstrap(EnviromentComponent, [
  HTTP_PROVIDERS,
  provide(RequestOptions, {useClass: ExRequestOptions})
]);

Ответ 4

Для более поздних версий angular вы не можете вызывать функции в декораторах. Вы должны использовать поставщика factory:

export function xsrfFactory() {
  return new CookieXSRFStrategy('_csrf', 'XSRF-TOKEN');
}

И затем используйте factory:

  providers: [
    {
      provide: XSRFStrategy,
      useFactory : xsrfFactory
  }],

В противном случае компилятор скажет вам. То, что я также видел, это то, что ng build -watch не сообщит об этой ошибке, пока вы не начнете ее снова.

Ответ 5

У Виктора К было решение, я просто добавлю здесь этот комментарий к тому, что я сделал:

Я создал компонент "ExRequestOptions", как сказал Виктор К, но я также добавил метод "appendHeaders" к этому компоненту:

appendHeaders(headername: string, headervalue: string) {
    this.headers.append(headername, headervalue);
}

Тогда у меня было это в моем main.ts:

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'
import {HTTP_PROVIDERS, RequestOptions} from 'angular2/http';
import 'rxjs/Rx';
import {ExRequestOptions} from './transportBoxes/exRequestOptions';
import {provide} from 'angular2/core';

bootstrap(AppComponent,[ HTTP_PROVIDERS,  
    provide(RequestOptions, {useClass: ExRequestOptions})]);

Я не уверен, что начальная загрузка имела какой-то эффект, поэтому я также сделал это, Я бы опубликовал данные:

    let options = new ExRequestOptions();
    options.appendHeaders('Content-Type', 'application/json');
    return this.http.post('.....URL', JSON.stringify(registration),
         options)

Ответ 6

В настоящее время я решаю что угодно с пользовательскими заголовками, используя сервис-обертку вокруг службы Http. Вы можете добавить любой заголовок вручную и добавить дополнительные сервисы для хранения/получения значений. Например, эта стратегия также работает для JWT. Посмотрите на код ниже, я надеюсь, что это поможет.

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

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

  private get xsrfToken() {
    // todo: some logic to retrieve the cookie here. we're in a service, so you can inject anything you'd like for this
    return '';
  }

  get(url) {
    return this.http.get(url, this.getRequestOptions())
      .map(result => result.json())
      .catch(error => error.json());
  }

  post(url, payload) {
    return this.http.post(url, payload, this.getRequestOptions())
      .map(result => result.json())
      .catch(error => error.json());
  }

  private getRequestOptions() {
    const headers = new Headers({'Content-Type': 'application/json', 'X-XSRF-TOKEN': this.xsrfToken});
    return new RequestOptions({headers: headers});
  }
}