![](/img/trans.png)
[英]Submit angular form to django backend with CSRF_COOKIE_HTTPONLY = True
[英]Pass Django CSRF token to Angular with CSRF_COOKIE_HTTPONLY
在 Django 中,當CSRF_COOKIE_HTTPONLY
設置為 True 時,CSRF cookie 獲得 httponly 標志,這從安全角度來看是可取的,但打破了將此 cookie 添加到 httpProvider 的標准角度解決方案,如下所示:
$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
通過 Django 1.9,有一個解決方法,您可以通過將 cookie 放入模板中直接將 cookie 傳遞給應用程序:
<script>
window.csrf_token = "{{ csrf_token }}";
</script>
並將其放入角度應用程序中:
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+ 發出 post 請求?
注意:禁用 CSRF 保護不是一個可接受的答案。
我認為這個問題在這次討論中得到了很好的回答。
https://groups.google.com/forum/#!topic/django-developers/nXjfLd8ba5k
https://code.djangoproject.com/ticket/27534
CSRF_COOKIE_HTTPONLY 不為單頁應用程序提供任何額外的安全性。 有些人推薦了這個解決方案
var csrftoken = getCookie('csrftoken');
if (csrftoken === null) {
csrftoken = $('input[name="csrfmiddlewaretoken"]').val();
if (csrftoken === null) {
console.log('No csrf token');
}
}
但是,或者如果您正在為您的應用程序公開 csrftoken,沒有什么可以阻止惡意用戶獲取並使用它。 如果您正在運行單頁應用程序,您不妨設置 CSRF_COOKIE_HTTPONLY=False,根據下面的評論:
加文·沃爾 5/4/15
怎么樣? 您不能只是從不同域中獲取 ajax 內容。
我說的是單個域。 在不包含 CSRF 令牌的頁面上注入 javascript 可以獲取同一域上的不同頁面以獲取它。
如果您已經將 javascript 注入到受害者頁面 (XSS) 中,則無需獲取 CSRF 令牌,您已經獲得了更大的控制權。
好吧,HttpOnly 標志旨在減少攻擊者一旦可以注入 javascript 就可以造成的損害。 但我同意——從 javascript 中隱藏 CSRF 令牌不會以任何方式增加安全性,但文檔暗示它確實如此。 我想在文檔中明確說明這個設置沒有任何意義。
如果您仍然認為那里有一個有效的攻擊向量,請將其發送到 secu...@djangoproject.com 並添加更多解釋。
沒有攻擊向量。 這只是關於誤導性的文檔。
Django 對此有一個文檔化的解決方案。 即使 CSRF_COOKIE_HTTPONLY 被啟用,只要 CSRF 令牌在 DOM 中,任何 Javascript 都可以從 DOM 中獲取 CSRF 令牌。
第 1 步:我添加一個標簽讓 Django 中間件將 csrf 令牌放入 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 } ]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.