我遇到的问题
- 我正在从我的 Angular2 客户端向我的 Django (v1.9) 后端发出一个 Ajax POST 请求(都在本地主机上,不同的端口)。我还没有使用 Django REST 框架,我只是在没有任何附加组件的情况下将 JSON 转储到 Django 中。
- 服务器已向我发出了一个csrf token ,我在 HTTP header 中手动将其发回(我可以在调用时在那里看到它)。
- 但是,我仍然收到来自 django 的错误:Forbidden (CSRF cookie not set.)
- 我已经阅读了许多其他线程,并尝试了一些方法,但仍然无法让 Django 接受 CSRF token 。
客户端代码:
private _editUserUri = "http://127.0.0.1:8000/search/edit/user/";
constructor(private _http: Http){}
getCookie(name) {
let value = "; " + document.cookie;
let parts = value.split("; " + name + "=");
if (parts.length == 2)
return parts.pop().split(";").shift();
}
validateData(userdata) {
return true;
}
editUser(userdata) {
console.log("UserService: createUser function called");
console.log(JSON.stringify(userdata));
if(this.validateData(userdata)) {
let headers = new Headers({
'Content-Type': 'application/json',
'X-CSRFToken': this.getCookie('csrftoken')
});
let options = new RequestOptions({ headers: headers });
return this._http
.post(
this._editUserUri,
JSON.stringify(userdata),
options)
.map(res => {
console.log(res.json());
return res.json();
})
}
}
header 中的 csrf token (x-csrftoken) 的屏幕截图。这正是 Django 所期望的 ( source )
我尝试过/考虑过的
我认为 csrf token 可能已过时。我试图生成一个新的,但我还没有设法让 Django 给我发一个新的。我试过使用 @ensure_csrf_cookie 装饰器,但仍然没有。如果我在今天早上放置的 cookie 中有一个 csrf token ,我是否希望它被一个新的、最新的版本替换?
另一个想法是 header 名称 (x-csrftoken) 是小写的。 Django 指定 header 名称应如下所示:X-CSRFToken。但是,从在线阅读看来,标题通常应该区分大小写。在任何情况下,Angular2 都会自动将 header 名称转换为小写。
我尝试了在 Stack Overflow ( example ) 上找到的其他一些解决方案,但没有成功。
我认为这可能与 CORS 有关,但第一个 OPTIONS 请求从我的 Django 服务器返回 200。此飞行前请求也不需要在其 header 中包含 csrf token ,对吗? (原谅我的无知)
我很确定我的设置没问题。我在 MIDDLEWARE_CLASSES、CSRF_COOKIE_SECURE = False、CORS_ALLOW_CREDENTIALS = True 和 CORS_ORIGIN_ALLOW_ALL = True
中有“django.middleware.csrf.CsrfViewMiddleware”
如果有人能提供帮助,我将不胜感激!
尼克
最佳答案
我认为问题在于您的请求只有 CSRF token header ,但没有 cookie(请参阅 double submit 针对 CSRF 的缓解措施,您发送的 header 应与 cookie 进行比较)。
虽然我不太明白到底发生了什么。如果您详细说明 Angular 应用程序的下载位置以及它如何从不同来源的 Django 获取 CSRF cookie,我可能可以编辑此答案以提供更多帮助。我不明白的是,如果 Angular 应用程序是从端口 A 下载的,那么它从哪里为端口 B 上的 Django 提供 CSRF cookie。
编辑:
啊,你正在使用 CORS。我认为您需要在 jQuery 请求中使用 withCredentials
以便 csrf cookie 随请求一起发送:
xhrFields: {
withCredentials: true
}
然后 Django 需要发送 Access-Control-Allow-Credentials: true
我想。
关于python - Angular2 和 Django : CSRF Token Headache,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39431386/