disable csrfmiddlewaretoken csrf_token django csrf angular django-csrf

csrfmiddlewaretoken - get csrf token django



¿Cuál es la forma correcta de utilizar las solicitudes http angular2 con la protección Django CSRF? (7)

En Angular1, el problema se puede resolver configurando $ http-provider. Me gusta:

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

¿Cuál es una buena práctica para hacer lo mismo en Angular2?

En Angular2 para trabajar con solicitudes http necesitamos usar la clase Http. Por supuesto, no es una buena práctica agregar una línea CSRF a cada llamada de la función posterior.

Supongo que en Angular2 debería crear una clase propia que herede la clase Http de Angular2 y redefinir la función posterior. ¿Es el enfoque correcto o hay un método más elegante?


Actualmente, resuelvo cualquier cosa con encabezados personalizados utilizando un servicio de envoltura alrededor del Servicio Http. Puede agregar cualquier encabezado manualmente e inyectar servicios adicionales para almacenar / recuperar valores. Esta estrategia también funciona para JWT, por ejemplo. Echa un vistazo al siguiente código, espero que te sirva de ayuda.

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


Ahora que se lanzó Angular 2, lo siguiente parece ser la forma correcta de hacerlo, utilizando la CookieXSRFStrategy .

He configurado mi aplicación para que tenga un módulo central, pero puede hacer lo mismo en su módulo de aplicación principal:

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


La respuesta de Victor K es perfectamente válida, sin embargo, a partir de angular 2.0.0-rc.2, un enfoque preferido sería utilizar la estrategia CookieXSRFS de la siguiente manera,

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


La solución para Angular2 no es tan fácil como para angular1. Necesitas:

  1. Elija el valor de la cookie csrftoken .

  2. Agregue este valor para solicitar encabezados con el nombre X-CSRFToken .

Ofrezco este fragmento:

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


Luché con esto por unos días. El consejo en este artículo es bueno, pero a partir de agosto de 2017 está en desuso ( https://github.com/angular/angular/pull/18906 ). El enfoque recomendado angular2 es simple, pero tiene una advertencia.

El enfoque recomendado es usar HttpClientXsrfModule y configurarlo para reconocer la protección csrf predeterminada de django. Según los docs django, django enviará la cookie csrftoken y esperará que el cliente devuelva el encabezado X-CSRFToken . En angular2, agregue lo siguiente a su app.module.ts

import { HttpClientModule, HttpClientXsrfModule } from ''@angular/common/http''; @NgModule({ imports: [ HttpClientModule, HttpClientXsrfModule.withOptions({ cookieName: ''csrftoken'', headerName: ''X-CSRFToken'', }) ], ...

La advertencia es que la protección XSRF de angular2 solo se aplica a las solicitudes de mutación:

De manera predeterminada, un interceptor envía esta cookie [encabezado] en todas las solicitudes de mutación (POST, etc.) a las URL relativas, pero no en las solicitudes GET / HEAD o en las solicitudes con una URL absoluta.

Si necesita admitir una API que realiza una mutación en GET / HEAD, deberá crear su propio interceptor personalizado. Puede encontrar un ejemplo y una discusión sobre el tema here .


Para versiones posteriores de angular, no puede llamar funciones en decoradores. Tienes que usar un proveedor de fábrica:

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

Y luego usa la fábrica:

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

De lo contrario, el compilador te delatará. Lo que también he visto es que ng build --watch no informará este error hasta que lo inicies nuevamente.


Victor K tuvo la solución, solo agregaré este comentario aquí sobre lo que hice:

Creé el componente "ExRequestOptions" como dijo Victor K, pero también agregué un método "appendHeaders" a ese componente:

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

Luego tuve esto en mi 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})]);

No estoy seguro de que el bootstrapping haya tenido algún efecto, así que también hice esto donde publicaría datos:

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