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

And*_*des 5 api django csrf django-csrf angularjs

从localhost机器向远程django api发出POST请求时,我收到CSRF令牌丢失或错误.

我在AngularJS上的设置:

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

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

}]);
Run Code Online (Sandbox Code Playgroud)

但我仍然得到CSRF令牌丢失或不正确的错误.

我检查发送的标题是什么,显然有角度没有发送HTTP_X_CSRFTOKEN.

但我可以看到cookie csrftoken =发送的东西.

有谁知道发生了什么?

请求标题

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
Run Code Online (Sandbox Code Playgroud)

Sha*_*rav 1

正如 @Chris Hawkes 指出 @Ye Liu 给出的 stackoverflow 答案

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

我验证了只要你不发出http get请求,csrftokencookie就不会被设置。所以只有

$httpProvider.defaults.xsrfCookieName = 'csrftoken';
$httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';
Run Code Online (Sandbox Code Playgroud)

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

更新:您的评论促使我进一步研究它,请阅读此博客,其中提到,

客户端生成的 CSRF 令牌。让客户端在 Cookie 和自定义 HTTP 标头中生成并发送相同的唯一秘密值。考虑到网站只允许读取/写入自己域的 Cookie,因此只有真实网站才能在两个标头中发送相同的值

因此,让我们首先尝试处理这个单一请求。

$http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken;
Run Code Online (Sandbox Code Playgroud)

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

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

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

var xsrfValue = urlIsSameOrigin(config.url)
            ? $$cookieReader()[config.xsrfCookieName || defaults.xsrfCookieName]
            : undefined;
        if (xsrfValue) {
          reqHeaders[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue;
        }
Run Code Online (Sandbox Code Playgroud)

因此,您有必要发送与 cookie 中存在的相同令牌。

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