Angular2和Django:CSRF令牌头痛 [英] Angular2 and Django: CSRF Token Headache

查看:450
本文介绍了Angular2和Django:CSRF令牌头痛的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有问题


  • 我从我的 > Angular2 客户端到我的 Django (v1.9)后端(在本地主机,不同端口上)。我还没有使用Django REST框架,我只是在Django中转载JSON,而没有任何加载项。

  • 我已经发出了一个 csrf令牌由服务器,我手动发回它在HTTP头(我可以看到它,当我打电话)。

  • 但是,我仍然从django收到错误:禁止(CSRF cookie未设置。)

  • 读了一些其他线程,并尝试了几件事情,但仍然无法让Django接受CSRF令牌。

  • I'm making an Ajax POST request from my Angular2 client to my Django (v1.9) backend (both on localhost, different ports). I'm not yet using the Django REST framework, I'm just dumping the JSON in Django without any add-ons.
  • I have been issued a csrf token by the server, and I'm manually sending it back in the HTTP headers (I can see it there when I make the call).
  • However, I still get the error from django: Forbidden (CSRF cookie not set.)
  • I've read a number of other threads, and tried a few things, but still can't get Django to accept the 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();
            })
    }

}

标题(x-csrftoken)中的csrf令牌的屏幕截图。这正是Django所期待的那样

我尝试过/考虑过


  • 我以为可能csrf令牌已经过时了。我试图生成一个新的,但我还没有设法让Django向我发出一个新的。我试过使用@ensure_csrf_cookie装饰器,但仍然没有。如果我今天早上在一个cookie中有一个csrf令牌,我希望它能被一个新的最新版本替换?

  • I thought that perhaps the csrf token is out of date. I've tried to generate a new one, but I haven't yet managed to get Django to issue me a new one. I've tried using the @ensure_csrf_cookie decorator, but still nothing. If I have a csrf token in a cookie which was placed this morning, would I expect it to be replaced by a new, up-to-date version?

X-CSRFToken 。然而,从在线阅读看来,标题通常应该区分大小写。在任何情况下,Angular2会自动将标题名称转换为小写。

Another thought was that the header name (x-csrftoken) is in lower case. Django specifies that the header name should be the following: X-CSRFToken. However, from reading online it seems that headers should generally be case sensitive. In any case, Angular2 is automatically converting the header name to lower case.

我尝试过在Stack Overflow中找到的其他一些解决方案(示例),但没有运气

I tried some other solutions I found on Stack Overflow (example) but had no luck.

我以为这可能与CORS有关,但第一个OPTIONS请求会从我的Django服务器返回200。这个飞行前请求不需要在其头中也包含csrf令牌,是吗? (恕我的无知)

I thought that maybe this was related to CORS, but the first OPTIONS request returns a 200 from my Django server. This pre-flight request wouldn't need to include the csrf token in its headers also, would it? (excuse my ignorance)

我很确定我的设置是正常的。我在MIDDLEWARE_CLASSES中有'django.middleware.csrf.CsrfViewMiddleware', CSRF_COOKIE_SECURE = False CORS_ALLOW_CREDENTIALS = True CORS_ORIGIN_ALLOW_ALL = True

I'm pretty sure my settings are fine. I have 'django.middleware.csrf.CsrfViewMiddleware' in MIDDLEWARE_CLASSES, CSRF_COOKIE_SECURE = False, CORS_ALLOW_CREDENTIALS = True and CORS_ORIGIN_ALLOW_ALL = True

如果有人可以帮助我非常感谢!

If anyone could help I'd greatly appreciate it!

推荐答案

我认为问题是您的请求只有CSRF令牌头,而不是cookie(请参阅双重提交对CSRF的缓解,您发送的标题应为与cookie相比)。

I think the problem is that your request only has the CSRF token header, but not the cookie (see the double submit mitigation against CSRF, the header you're sending should be compared to the cookie).

我不太明白究竟发生了什么。如果您详细说明了Angular应用程序从哪里下载,以及如何从Django获取CSRF cookie,这是不同的起源,我可以编辑这个答案来帮助更多。我没有得到的是,如果Angular应用程序从端口A下载,从哪里在端口B上有Django的CSRF cookie。

I don't quite understand what exactly is happening though. If you elaborate a bit more on where the Angular app is downloaded from and how it gets the CSRF cookie from Django, which is a different origin, I can probably edit this answer to help more. What I don't get is that if the Angular app is downloaded from port A, from where does it have a CSRF cookie for Django on port B.

编辑:

您正在使用CORS。我想你在jQuery请求中需要 withCredentials ,以便csrf cookie与请求一起发送:

Ah you're using CORS. I think you need withCredentials in the jQuery request so that the csrf cookie is sent with the request:

xhrFields: {
    withCredentials: true
}

Django然后需要发送 Access-Control-Allow-Credentials:true 我想。

Django then needs to send Access-Control-Allow-Credentials: true I think.

这篇关于Angular2和Django:CSRF令牌头痛的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆