CSRF 令牌丢失或不正确。 Django + AngularJS

Posted

技术标签:

【中文标题】CSRF 令牌丢失或不正确。 Django + AngularJS【英文标题】:CSRF token missing or incorrect. Django + AngularJS 【发布时间】:2016-06-10 05:27:57 【问题描述】:

我在从本地计算机向远程 django api 发出 POST 请求时收到 CSRF 令牌丢失或不正确的错误。

我在 AngularJS 上的设置:

.config(['$httpProvider', function($httpProvider)

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

]);

但我仍然收到 CSRF 令牌丢失或不正确错误。

我检查正在发送哪些标头,显然 Angular 没有发送 HTTP_X_CSRFTOKEN

但我可以看到 cookie csrftoken=something 已发送。

有人知道怎么回事吗?

请求标头

POST /s/login/ HTTP/1.1
Host: server.somewhere.io:8000
Connection: keep-alive
Content-Length: 290
Pragma: no-cache
Cache-Control: no-cache
Accept: application/json, text/plain, */*
Origin: http://localhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/48.0.2564.116 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost/thesocialmarkt/
Accept-Encoding: gzip, deflate
Accept-Language: en-GB,en;q=0.8,en-US;q=0.6,pt-BR;q=0.4,pt;q=0.2
Cookie: csrftoken=hiYq1bCNux1mTeQuI4eNgi97qir8pivi; sessionid=1nn1phjab5yd71yfu5k8ghdch2ho6exc

【问题讨论】:

这是重复的吗? ***.com/questions/18156452/… 不是因为我还有这个问题。 你的 django restframework 设置是什么? 我们没有使用 Django Rest 框架,我们的 API 是在 Django 中原生构建的 【参考方案1】:

正如@Chris Hawkes 指出@Ye Liu 给出的这个*** 答案

由于 django 不提供 Angular 应用程序,为了让 要设置的 cookie,角度应用程序需要向 django 发出 GET 请求 首先。

我证实,只要您不发出 http get 请求,csrftoken cookie 就不会被设置。所以只有

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

行不通。如果不是真的,您首先需要向 django rest_framework 模拟 http get 请求。

更新:您的 cmets 促使我进一步研究它,请阅读此 blog 已提及的地方,

客户端生成的 CSRF 代币。让客户端生成并发送 Cookie 和自定义 HTTP 中的相同唯一秘密值 标题。考虑到一个网站只允许读/写一个 Cookie 对于自己的域,只有真实站点可以在两者中发送相同的值 标题

所以让我们先尝试这个单一的请求。

$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;

您将$cookies 注入控制器/服务的位置。

如果它有效,那么可能写interceptors 会是不错的选择,也可以帮助您进行调试。

我确定您使用的 AngularJs 版本至少为 1.2,请参阅changeset 并在最近提交的 Angular http 服务中使用此代码检查 csrf,

var xsrfValue = urlIsSameOrigin(config.url)
            ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
            : undefined;
        if (xsrfValue) 
          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
        

因此,您必须发送与 cookie 中相同的令牌。

进一步分析使用浏览器的开发工具来查看对 http 请求的请求/响应并分析标头和 cookie。

【讨论】:

我在页面加载时执行获取请求。所以我得到了 CSRFTOKEN 的响应。正如您在我上面发布的 resquest 标头中看到的那样,cookie csrftoken=hiYq1bCNux1mTeQuI4eNgi97qir8pivi;被设置。发生的事情是当我尝试执行另一个请求时,django 说我没有发送令牌。我注意到标头 HTTP_X_CSRFTOKEN 没有发送。 感谢您的帮助。但我想只要我在本地机器上它就不会真正起作用。稍后我会将其上传到服务器并进行测试。【参考方案2】:

如果您在 AngularJS 中使用 $http 进行 ajax 请求,并且遇到任何 CSRF 令牌问题,请使用:

$http.defaults.xsrfCookieName = 'csrftoken';
$http.defaults.xsrfHeaderName = 'X-CSRFToken';

【讨论】:

以上是关于CSRF 令牌丢失或不正确。 Django + AngularJS的主要内容,如果未能解决你的问题,请参考以下文章

Django:CSRF 令牌丢失或不正确。 / 避免 % csrf_token %

CSRF 令牌丢失或不正确。 Django + AngularJS

Django - 403 禁止。 CSRF 令牌丢失或不正确

Django 表单中的 CSRF 令牌丢失或不正确

Unity Web Request + Django:CSRF 令牌丢失或不正确

禁止(CSRF 令牌丢失或不正确。)Django