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 令牌丢失或不正确