简体   繁体   English

Django 1.9 AJAX表单CSRF令牌403错误 - “未设置CSRF cookie”

[英]Django 1.9 AJAX form CSRF token 403 error - “CSRF cookie not set”

I've seen a lot about this on SO, but nothing can fix my problem. 我已经在SO上看到了很多,但没有什么能解决我的问题。

Problem: 问题:

With CSRF middleware enabled, Django responds with 403 on AJAX form request, stating: 启用CSRF中间件后,Django在AJAX表单请求上响应403,说明:

"CSRF cookie not set." “未设置CSRF cookie。”

Following the documentation , a JS functionality was implemented, that sets custom "X-CSRFToken" header. 文档之后 ,实现了一个JS功能,它设置了自定义的“X-CSRFToken”标头。

It works as expected, gets "csrftoken" cookie from browser and posts it along with AJAX request: 它按预期工作,从浏览器获取“csrftoken” cookie并将其与AJAX请求一起发布:

x-csrftoken: 1a0u7GCQG0wepZHQNThIXeYpMy2lZOf2

But response is still 403. 但回应仍然是403。

Tried solutions: 尝试的解决方案:

I've tried everything I could find on SO or web, specifically: 我已经尝试过在SO或网上找到的所有内容,特别是:

  • Checking that middleware is enabled: 检查是否启用了中间件:

     MIDDLEWARE_CLASSES = [ ... 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', ... ] 
  • Different browsers with cookies enabled; 启用了Cookie的不同浏览器;

  • Decorating my view with @ensure_csrf_cookie ; @ensure_csrf_cookie装饰我的观点;

  • Setting {% csrf_token %} in my template; 在我的模板中设置{% csrf_token %} ;

  • Using render shortcut which takes right request context; 使用获取正确请求上下文的render快捷方式

  • Setting custom CSRF_COOKIE_NAME and CSRF_HEADER_NAME in my settings.py ; 在我的settings.py设置自定义CSRF_COOKIE_NAMECSRF_HEADER_NAME ;

  • Explicitly setting CSRF_COOKIE_SECURE = False and CSRF_COOKIE_HTTPONLY = False ; 明确设置CSRF_COOKIE_SECURE = FalseCSRF_COOKIE_HTTPONLY = False ;

  • Explicitly setting CSRF_TRUSTED_ORIGINS setting; 明确设置CSRF_TRUSTED_ORIGINS设置;

  • Testing on development and production server; 测试开发和生产服务器;

  • Even request.META["CSRF_COOKIE_USED"] = True in my view, as someone suggested. 甚至request.META["CSRF_COOKIE_USED"] = True在我看来是request.META["CSRF_COOKIE_USED"] = True ,正如有人建议的那样。

And still got nothing. 仍然一无所获。

Headers: 头:

If I use @csrf_exempt and print(request.META) in my view, it's clear that custom header "X-CSRFToken" is present in request and formatted according to Django documentation, with "HTTP_" prefix, replaced hyphens with underscores, all uppercase: "HTTP_X_CSRFTOKEN" . 如果我在我的视图中使用@csrf_exemptprint(request.META) ,很明显请求中存在自定义标题“X-CSRFToken” ,并根据Django文档格式化,带有“HTTP_”前缀,用下划线替换连字符,全部大写: “HTTP_X_CSRFTOKEN”

Even more, it's value matches with cookie set by Django. 更重要的是,它的价值与Django设置的cookie相匹配。

Cookies: 饼干:

Strange thing is, if I try to print(request.COOKIES) in my view, on page and form load I can see "csrftoken" cookie there, but dictionary is empty on AJAX request . 奇怪的是,如果我尝试在我的视图中print(request.COOKIES) ,在页面和表单加载上我可以看到“csrftoken” cookie,但字典在AJAX请求时空的 Can it be the problem? 这可能是问题吗?

Desperate to find what is actually wrong. 不顾一切地发现实际上是错的。 Thank you for reading this. 谢谢您阅读此篇。

Ok, the issue is quite simple then: 好的,问题很简单:

Fetch API is not sending credentials by default. 默认情况下,Fetch API不会发送凭据。 According to MDN : MDN称

The credentials read-only property of the Request interface indicates whether the user agent should send cookies from the other domain in the case of cross-origin requests. Request接口的凭证只读属性指示用户代理是否应在跨源请求的情况下从其他域发送cookie。 This is similar to XHR's withCredentials flag, but with three available values. 这类似于XHR的withCredentials标志,但有三个可用值。

Default is omit , and it never sends cookies. 默认为omit ,它永远不会发送cookie。 You just need to add same-origin to your fetch() function arguments: 您只需要在fetch()函数参数中添加same-origin

fetch(formUrl, {
    ...
    credentials: 'same-origin',
    ...
})

And you'll be good to go : ) 你会很高兴去:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM