angularjs - 使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF token 传递给 Angular

标签 angularjs django cookies csrf django-csrf

在 Django 中,当 CSRF_COOKIE_HTTPONLY 设置设置为 True 时,CSRF cookie 会获得 httponly 标志,从安全 Angular 来看这是理想的,但破坏了将此 cookie 添加到httpProvider 像这样:

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

通过 Django 1.9,有一个解决方法,您可以将 cookie 直接传递到应用程序,方法是将其放入模板中:

<script>
    window.csrf_token = "{{ csrf_token }}";
</script>

并将其放入 Angular 应用程序中:

angularApp.config(["$httpProvider", function($httpProvider) {
    $httpProvider.defaults.headers.common["X-CSRFToken"] = window.csrf_token;
}]

不幸的是,这不适用于 Django 1.10+ 中的单页 Angular 应用程序,因为 CSRF cookie 在每次请求后都会更改。如何在启用 CSRF_COOKIE_HTTPONLY 设置的情况下从 Angular 向 Django 1.10+ 发出发布请求?
注意:禁用 CSRF 保护不是一个可接受的答案。

最佳答案

Django has a documented solution for this 。即使启用了 CSRF_COOKIE_HTTPONLY,只要 CSRF token 位于 DOM 中,任何 Javascript 都可以从 DOM 获取 CSRF token 。

第 1 步:我添加一个标签,让 Django 中间件将 csrf token 放入 DOM

# Django put CSRF token to DOM
{% csrf_token %}

第 2 步:实现 HttpInterceptor 以从 DOM 获取 csrf

import { Injectable } from '@angular/core';
import { HttpEvent, HttpRequest, HttpHandler, HttpInterceptor } from '@angular/common/http';
import { Observable } from 'rxjs';

@Injectable()
export class DjangoCSRFInterceptor implements HttpInterceptor {
  intercept(httpRequest: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = (
      document.querySelector('[name=csrfmiddlewaretoken]') as HTMLInputElement
    ).value;
    return httpRequest.clone({ headers: httpRequest.headers.set('X-CSRFToken, token) });
  }
}

第 3 步:将 HttpInterceptor 添加到您的 Angular 模块提供程序

providers: [
  { provide: HTTP_INTERCEPTORS, useClass: DjangoCSRFInterceptor, multi: true }
]

关于angularjs - 使用 CSRF_COOKIE_HTTPONLY 将 Django CSRF token 传递给 Angular,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40851475/

相关文章:

javascript - 能够访问服务返回的对象,但访问其属性给出未定义

Django url templatetag(但不是rev​​erse())错误: Caught NoReverseMatch while rendering

django - 可选的ImageField(Django)

java - 使用 Jersey 的 session Cookie

authentication - 保留身份验证 cookie,但不允许在不同站点并发访问

javascript - angularjs http + script7002 : xmlhttprequest: network error 0x80070005, 访问被拒绝

jquery - Angularjs动态调整iframe高度

php - 无法打开流 : No such file of directory in. .. PHP fopen

javascript - 单击按钮时执行 ng-include - Angularjs

python - 如何使用 gunicorn 在 django 中编写 log.info() 以进行控制台?