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 中设置 [重复]