2015-12-28 9 views
17

In Angular1 il problema può essere risolto configurando $ http-provider. Ad esempio:Qual è il modo corretto di utilizzare le richieste http angular2 con la protezione di Django CSRF?

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

Qual è una buona pratica per fare lo stesso in Angular2?

In Angular2 per lavorare con le richieste http è necessario utilizzare la classe Http. Ovviamente non è una buona pratica aggiungere CSRF-line ad ogni chiamata di post-funzione.

Immagino che in Angular2 dovrei creare una propria classe che erediti la classe Http di Angular2 e ridefinire la funzione post. È l'approccio giusto o esiste un metodo più elegante?

+0

sì, possiamo un servizio globale e puoi scrivere qualsiasi cosa tu desideri nell'intera tua app. quindi fornire tale servizio globale nel file bootstrap. Penso che questo ti dia un suggerimento –

+0

Ora che la versione 2.0 è stata rilasciata ufficialmente, le risposte precedenti non sembrano più funzionare. Si prega di vedere la mia risposta di seguito su come utilizzare CookieXSRFStrategy. – David

risposta

10

risposta di Victor K è perfettamente valido comunque come di angolare 2.0.0-rc.2, un approccio preferito sarebbe quello di utilizzare CookieXSRFStrategy come sotto,

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

poiché la fornitura è stata deprecata, immagino che il nuovo modo dovrebbe essere quello di sostituire la linea di fornitura con '{fornire: XSRFStrategy, useValue: new CookieXSRFStrategy ('csrftoken', 'X-CSRFToken')}' – maxbellec

+0

Questa soluzione non funziona nella versione di rilascio di Angular 2. Vedi la mia risposta di seguito. – David

13

Soluzione per Angular2 non è facile come per angular1. Hai bisogno di:

  1. scegliere valore csrftoken biscotto.

  2. Aggiungere questo valore per richiedere le intestazioni con nome X-CSRFToken.

Offro questo frammento:

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}) 
]); 
+1

Immagino che dovresti accettare la tua risposta. –

+0

Victor, hai bisogno di fare qualcosa di speciale per ottenere il cookie dal server Django? Quando controllo i cookie, csrftoken non esiste. –

+0

Sì, la funzione di visualizzazione deve essere decorata con @csrf_protect o la classe CsrfViewMiddleware deve essere aggiunta a MIDDLEWARE_CLASSES nel file delle impostazioni. Dettagli qui https://docs.djangoproject.com/en/1.9/ref/csrf/#module-django.views.decorators.csrf –

2

Victor K ha avuto la soluzione, mi limiterò a aggiungere questo commento qui da quello che ho fatto:

ho creato il componente "ExRequestOptions" come diceva Victor K, ma ho anche aggiunto un metodo "appendHeaders" a tale componente:

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

Poi ho avuto nei miei 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})]); 

io non sono sicuro che il bootstrap ha avuto alcun effetto, così ho fatto anche questo, dove Vorrei inviare i dati:

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

Ora che Angul ar 2 viene rilasciato il seguente sembra essere il modo corretto di farlo, utilizzando CookieXSRFStrategy.

ho configurato la mia domanda per avere un core module ma si può fare lo stesso nel modulo principale, invece:

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 { 
}, 
+0

Salve al primo tentativo di esecuzione ho ricevuto questo errore: 'ERRORE in Errore ha riscontrato la risoluzione statica dei valori dei simboli. Chiamando la funzione 'CookieXSRFStrategy', le chiamate di funzione non sono supportate. Considera la possibilità di sostituire t la sua funzione o lambda con un riferimento a una funzione esportata'. Ma comunque quando si colpisce salva il cli si sta ricostruendo ma ora senza errori. –

+1

@ ShiftN'Tab è possibile sostituire 'new CookieXSRFStrategy ('csrftoken', 'X-CSRFToken')' con una funzione che restituisce tale riga. Questo dovrebbe risolverlo. – callback

1

Attualmente, risolve nulla con le intestazioni personalizzate utilizzando un servizio di wrapper per il servizio HTTP . È possibile aggiungere qualsiasi intestazione manualmente e iniettare servizi aggiuntivi per l'archiviazione/il recupero dei valori. Questa strategia funziona anche per le JWT, ad esempio. Dai un'occhiata al codice qui sotto, spero che aiuti.

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

Per le versioni successive di angolari non è possibile chiamare le funzioni nei decoratori.È necessario utilizzare un provider di fabbrica:

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

e quindi utilizzare la fabbrica:

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

In caso contrario, il compilatore vi dirà off. Quello che ho anche visto è che ng build --watch non segnalerà questo errore finché non lo avvii di nuovo.

Problemi correlati