XSRF 标头未在 AngularJS 中设置

Posted

技术标签:

【中文标题】XSRF 标头未在 AngularJS 中设置【英文标题】:XSRF headers not being set in AngularJS 【发布时间】:2013-08-22 12:15:34 【问题描述】:

我正在开发一个 DJANGO + AngularJS 应用程序,其中 Angular 部分没有由 django 提供服务。

我将角度$httpProvider设置如下:

myApp = angular.module('myApp', [])

myApp.config(['$httpProvider',
  function(provider)
    provider.defaults.xsrfCookieName = 'csrftoken';
    provider.defaults.xsrfHeaderName = 'X-CSRFToken';

然后,在执行任何 POST 之前,我会执行一个设置 cookie 的 GET。我可以通过 Chrome 确认 cookie 已设置:

set-cookie:csrftoken=hg88ZZFEdLPnwDdN1eiNquA8YzTySdQO; expires=Tue, 19-Aug-2014 12:26:35 GMT; Max-Age=31449600; Path=/

(在 Chrome 开发者工具的 resources/cookies/localhost 中可见)

但是,当我进行 POST 时,没有设置 X-CSRFToken 标头

这是 Chrome 记录的 POST:

POST /data/activities/search HTTP/1.1
Host: localhost:14080
Connection: keep-alive
Content-Length: 2
Accept: application/json, text/plain, */*
Origin: http://localhost:14080
X-Requested-With: XMLHttpRequest
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_4) AppleWebKit/537.36 (Khtml, like Gecko) Chrome/28.0.1500.95 Safari/537.36
Content-Type: application/json;charset=UTF-8
Referer: http://localhost:14080/public/html/main.html?codekitCB=398694184.799418
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Cookie: csrftoken=hg88ZZFEdLPnwDdN1eiNquA8YzTySdQO

为什么没有设置标题?我还应该做什么来激活此功能?

(旁注:如果我在 $http() 调用中手动传递标头,则 POST 请求可以正常工作。因此问题实际上是 AngularJS 没有设置标头)

【问题讨论】:

我使用的是 1.0.8,但我发现它仅适用于 1.2.0 版本 【参考方案1】:

非常简单的答案:它仅适用于版本 1.2.0,目前是候选版本。

【讨论】:

@OZ_ 谁说 1.1.5,谁说 1.0.x :) 不,这是正确的,新的自动方式(这个问题的一个对象)仅来自 angular 1.2,您正在手动进行(仍然有用) 值得注意的是,如果您使用带有响应上下文的 django 视图,如果模板中没有表单(通常不会有),您仍然没有 csrf_token。这就是为什么您可能需要使用 ensure_csrf_cookie 装饰器,以便 Angular api 调用将具有他们需要的令牌。【参考方案2】:
app.config(["$httpProvider", function($httpProvider) 
    var csrfToken = getCookie('csrftoken');
    $httpProvider.defaults.headers.common['X-CSRFToken'] = csrfToken; 
])

getCookie() 取自https://docs.djangoproject.com/en/dev/ref/contrib/csrf/


或者分别设置各个方法

 $httpProvider.defaults.headers.post['X-CS....
 $httpProvider.defaults.headers.get['X-CS....

【讨论】:

【参考方案3】:

在使用 Safari 或 Firefox 时,1.2.0 更新对我来说还不够(Chrome 一直运行良好)。 Safari 和 Firefox 的问题是 Django 后端没有在 HTTP 响应中发送 csrf-cookie。

我要做的就是将 @ensure_csrf_cookie 装饰器添加到我的视图函数中,该函数为 Angularjs 构建页面。

@ensure_csrf_token
def my_view(request):
    ...

javascript 文件中:

myApp.config(function($httpProvider) 
    $httpProvider.defaults.xsrfCookieName = 'csrftoken';
    $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken';

至少现在我不知道为什么 Chrome 没有它可以工作,而其他浏览器却不能。

【讨论】:

如何导入@ensure_csrf_token? 呃,我想我在这个例子中有一个错字。它是@ensure_csrf_cookie,可以在 django.views.decorators.csrf.ensure_csrf_cookie 中找到【参考方案4】:

我遇到了类似的问题,这是我的错。

我的错误:

$.post('/url', data)

确保您使用的是$http 对象!

$http.post('/url', data)

很容易犯这个错误,因为两者看起来都一样好用,除了前者不看$http.defaults.headers.common['X-CSRFToken'],等等。

【讨论】:

嘿。好贴。我没有这样做,但它让我发痒。很高兴分享你的红脸时刻!【参考方案5】:

Angular 变化非常频繁,有些答案不适用于最新版本。无论如何,由于 Angular 需要一个 XSRF-TOKEN cookie 名称,并发送一个 X-XSRF-TOKEN 标头,我们也可以简单地告诉 Django 默认使用它们:

CSRF_COOKIE_NAME = 'XSRF-TOKEN'
CSRF_HEADER_NAME = 'HTTP_X_XSRF_TOKEN'

第一个设置(参见 docs)是 csrf 令牌的 cookie 名称,而第二个设置(参见 docs,仅在 1.9 中引入)是相应的标头名称。

最后,仅供参考,别忘了设置:

CSRF_COOKIE_HTTPONLY = False

【讨论】:

以上是关于XSRF 标头未在 AngularJS 中设置的主要内容,如果未能解决你的问题,请参考以下文章

Spring security + session:接收“Set-Cookie”标头但未在浏览器中设置

express-jwt 和带有 cookie 的 Angular 9:未在“授权”标头中设置令牌

在 AngularJS 中设置应用程序范围的 HTTP 标头

连接到 slack api 中的 chat.postMessage 的 CORS 策略错误,标头已设置但未在 React 和 Redux 中设置 [重复]

使用 X-XSRF-TOKEN(如 angularjs)标头确保 CSRF 保护

[PHP警告:mail():“sendmail_from”未在php.ini中设置或自定义“From:”标头丢失