python - Angular2 和 Django : CSRF Token Headache

标签 python django angular cors csrf

我遇到的问题

  • 我正在从我的 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 ) Screenshot

我尝试过/考虑过的

  • 我认为 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 = FalseCORS_ALLOW_CREDENTIALS = TrueCORS_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/

相关文章:

python - Elasticsearch在Python控制台上打印PUT语句

python - 如何修复错误 "_core.QgsProcessingException: There were errors executing the algorithm."

python - 如何在settings.py中获取主机名或IP,以便我可以使用它来决定要使用哪个应用程序的网址

在 Web Worker 中导入 tensorflow 时出现 Angular typescript 类型检查问题

ionic-framework - 使用 Angular 2 更改值时调用方法

python - 如何更改 Pandas 箱线图中 mustache 的线条样式?

python - 使用python api递归计算每个保管箱文件夹的大小

python - 如何在 Django 休息框架响应中获取过滤的 Django ORM 查询结果

python - django-图像裁剪不起作用

angular - 从 Angular 4 中的另一个组件访问组件方法