首页 文章

使用带有Django CSRF保护的angular2 http请求的正确方法是什么?

提问于
浏览
17

在Angular1中,可以通过配置$ http-provider来解决问题 . 喜欢:

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

在Angular2中做同样的事情有什么好处?

在Angular2中使用http请求我们需要使用类Http . 当然,在每个后期函数调用中添加CSRF-line并不是一个好习惯 .

我想在Angular2中我应该创建自己的类来继承Angular2的Http类并重新定义后期函数 . 这是正确的方法还是有更优雅的方法?

7 回答

  • 10

    对于更高版本的角度,您无法在装饰器中调用函数 . 您必须使用工厂提供商:

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

    然后使用工厂:

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

    否则编译器会告诉你 . 我还看到,在你再次启动之前,ng build --watch不会报告此错误 .

  • 18

    Victor K的答案是完全有效的,但是从角度2.0.0-rc.2开始,首选的方法是使用如下的CookieXSRFStrategy,

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

    现在Angular 2被释放了,通过使用 CookieXSRFStrategy ,以下似乎是正确的方法 .

    我已将我的应用程序配置为core module,但您可以在主应用程序模块中执行相同操作:

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

    Angular2的解决方案并不像angular1那么容易 . 你需要:

    • 挑出 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})
    ]);
    
  • 13

    Victor K有解决方案,我只是在这里添加这个评论我做了什么:

    正如Victor K所说,我创建了组件“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})]);
    

    我不确定bootstrapping是否有任何影响,所以我也在这里发布数据:

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

    我挣扎了几天 . 本文中的建议很好,但截至2017年8月已被弃用(https://github.com/angular/angular/pull/18906) . angular2推荐的方法很简单,但有一点需要注意 .

    建议的方法是使用HttpClientXsrfModule并将其配置为识别django的默认csrf保护 . 根据django docs,django将发送cookie csrftoken 并期望客户端返回标头 X-CSRFToken . 在angular2中,将以下内容添加到 app.module.ts

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

    需要注意的是,angular2的XSRF Protection仅适用于变异请求:

    默认情况下,拦截器会将所有变异请求(POST等)上的cookie [header]发送到相对URL,但不会发送给GET / HEAD请求或带有绝对URL的请求 .

    如果您需要支持在GET / HEAD上执行变异的API,则需要创建自己的自定义拦截器 . 您可以找到问题的示例和讨论here .

  • 1

    目前,我使用围绕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});
      }
    }
    

相关问题