django 在 cookie 中没有 csrftoken
Posted
技术标签:
【中文标题】django 在 cookie 中没有 csrftoken【英文标题】:django no csrftoken in cookie 【发布时间】:2012-11-04 22:42:18 【问题描述】:我正在测试发出 POST ajax 请求,但由于没有 csrftoken,我得到了 403。我跟着文档,但是还是不行,发现名为csrftoken的cookie是empty,意思是$.cookie("csrftoken")
return null。
谁能告诉我原因以及如何将csrftoken
设置到cookie 中?
【问题讨论】:
之前有过类似的问题,与 csrf_protect 装饰器有关。如果您从一个页面发布到另一个 url(例如 ajax)并且如果您使用的是 @csrf_protect 装饰器等,请确保两者查看您发布数据的来源以及接收发布数据的 url 以拥有此装饰器。 你的观点,你的模板表单? 【参考方案1】:我认为您应该提供如何在 html/JS 代码和中间件设置中获取 csrf 令牌的代码。
首先您应该检查django.middleware.csrf.CsrfViewMiddleware
是否已打开。
我遇到了类似的问题,在 python 代码中我使用request.META.get('CSRF_COOKIE')
来获取令牌。
当您在模板中使用此令牌时 - % csrf_token %
Django 注意到该令牌已被渲染并在 CsrfViewMiddleware.process_response
中设置 Cookie。如果您以其他方式获取令牌值,Django 将错过此标志。所以它会为你生成一个令牌,但不会设置相应的cookie。
我在代码中有 2 个解决方法。您应该将其添加到用于生成带有 JS 代码的模板的视图中。
1.你可以强制Django设置CSRF Cookie:
# Force updating CSRF cookie
request.META["CSRF_COOKIE_USED"] = True
2.如果你调用get_token
,Django会自动设置CSRF_COOKIE_USED
from django.middleware.csrf import get_token
# don't use direct access to request.META.get('CSRF_COOKIE')
# in this case django will NOT send a CSRF cookie. Use get_token function
csrf_token = get_token(request)
每个解决方案都应该单独工作。我建议使用get_token
【讨论】:
【参考方案2】:您可能想要使用 ensure_csrf_cookie
视图装饰器(从 Django 1.4 开始可用)。即使您不使用 csrf_token
模板标签,这也会设置csrftoken
cookie。
【讨论】:
【参考方案3】:我遇到了同样的问题($.cookie('csrftoken') 返回了 'undefined')。
问题出在我的 Django 配置中,我注释了以下行并且它有效:
#CSRF_COOKIE_HTTPONLY = True # Prevent client-side javascript access to the CSRF cookie
【讨论】:
是的,http-only cookie 无法通过浏览器中的 javascript 访问。 @o_c 你在哪里评论?【参考方案4】:在o_c's answer 上扩展:通过注释CSRF_COOKIE_HTTPONLY
行,csrf_token 值不再是“未定义”(在 Firefox firebug 中)并显示为“真实”值,例如'qGuPe2Q7...等'。
Ajax 请求不再因403 Forbidden
错误而被拒绝,并且被正确执行(前提是在 AJAX 标头中设置了 csrf_token)。
$.ajaxSetup(
beforeSend: function(xhr, settings)
if (!csrfSafeMethod(settings.type) && !this.crossDomain)
xhr.setRequestHeader("X-CSRFToken", csrftoken);
);
【讨论】:
如何在前端获取csrftoken
?【参考方案5】:
首先,如果您正在设计应用程序,最好在标头或 POST 请求中使用 csrf Token,而不是在 cookie 中,因为:
所有表单都必须将值动态添加到其 HTML 中。任何 AJAX POST 还必须包含该值。 将为每个请求提交 cookie(即所有 GET 图片、CSS、JS等不参与CSRF流程) 增加请求大小。如果你想在 django 中强制使用 cookie,你总是可以:
request.META["CSRF_COOKIE_USED"] = True
如果您没有在任何地方使用 % csrf_token % 在您的项目中。根据 [documentation][1],您不需要做任何其他事情,只需编写一个简单的 javascript 代码即可。其实这不是真的。您必须在每个视图中放置"request.META['CSRF_COOKIE_USED'] = True"
行(或编写适当的装饰器)。
【讨论】:
您是否考虑过对文档提出拉取请求以包含此内容?以上是关于django 在 cookie 中没有 csrftoken的主要内容,如果未能解决你的问题,请参考以下文章
Django + ReactJS。 Httponly cookie 没有保存在 React 端的浏览器中。我还在两边都给了 withcredentials : true
Django REST Framework - 没有通过 Response.set_cookie() 调用设置 cookie...?