在 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/