我遇到的问题
- 我从我的Angular2客户端向我的Django(v1.9)后端发出了一个Ajax POST请求(两者都在本地主机上,不同的端口)。 我尚未使用Django REST框架,我只是在Django中转储JSON而没有任何附加组件。
- 服务器已向我发出csrf令牌,并且我在HTTP头中手动发送它(当我进行调用时,我可以看到它存在于那里)。
- 但是,我仍然收到来自Django的错误:Forbidden (CSRF cookie not set.)
- 我已经阅读了一些其他帖子,并尝试了一些方法,但仍然无法使Django接受CSRF令牌。
客户端代码:
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();
})
}
}
在头部中的csrf token截图(x-csrftoken)。这正是Django所期望的 (来源)
我尝试过/考虑过以下方法:
我认为可能csrf token已经过期了。我尝试生成一个新的,但我还没有成功让Django发放给我一个新的。我尝试使用@ensure_csrf_cookie装饰器,但仍然没有用。如果我有一个csrf token在今天早上放置的cookie中,我是否应该期望它被一个新的、最新的版本替换?
另一个想法是,头部名称(x-csrftoken)是小写的。Django指定头部名称应该是以下内容:X-CSRFToken。然而,从在线阅读中,似乎头部通常区分大小写。无论如何,Angular2自动将头部名称转换为小写。
我尝试了一些我在Stack Overflow上找到的其他解决方案(示例),但没有成功。
我认为这可能与CORS有关,但我的Django服务器从第一个OPTIONS请求返回200。这个预检请求不需要在它的头部中包含csrf token,对吗?(请原谅我的无知)
我很确定我的设置是正确的。我在MIDDLEWARE_CLASSES中有'django.middleware.csrf.CsrfViewMiddleware',CSRF_COOKIE_SECURE = False,CORS_ALLOW_CREDENTIALS = True和CORS_ORIGIN_ALLOW_ALL = True
如果有人可以帮忙,我将非常感激!
Nick
csrfmiddlewaretoken
POST 参数中。不确定标题名称是否区分大小写,但您可以通过使用不会将其转换为小写的工具(例如jquery)进行POST请求来检查它。 - serg