我遇到的问题
客户端代码:
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标记的屏幕截图(x-csrftoken)。这正是Django的预期(source)
我尝试/考虑的内容
我想也许csrf令牌已经过时了。我试图创造一个新的,但我还没有设法让Django给我一个新的。我尝试过使用@ensure_csrf_cookie装饰器,但仍然没有。如果我在今天早上放置的cookie中有一个csrf令牌,我是否希望它被一个新的最新版本取代?
另一个想法是标题名称(x-csrftoken)是小写的。 Django指定标题名称应为以下内容: X-CSRFToken 。但是,通过在线阅读,标题通常应该区分大小写。在任何情况下,Angular2都会自动将标题名称转换为小写。
我尝试了一些我在Stack Overflow上发现的其他解决方案(example),但没有运气。
我认为这可能与CORS有关,但第一个OPTIONS请求从我的Django服务器返回200。这个飞行前请求也不需要在其标题中包含csrf令牌,是吗? (原谅我的无知)
我很确定我的设置很好。我有&#d; django.middleware.csrf.CsrfViewMiddleware'在MIDDLEWARE_CLASSES中, CSRF_COOKIE_SECURE = False , CORS_ALLOW_CREDENTIALS = True 和 CORS_ORIGIN_ALLOW_ALL = True
如果有人可以提供帮助,我会非常感激!
尼克
答案 0 :(得分:2)
我认为问题在于您的请求只有CSRF令牌标头,而不是Cookie(请参阅double submit针对CSRF的缓解,您要发送的标头应与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
。