Django 1.9 AJAX形式CSRF令牌403错误 - “CSRF cookie not set” [英] Django 1.9 AJAX form CSRF token 403 error - "CSRF cookie not set"

查看:150
本文介绍了Django 1.9 AJAX形式CSRF令牌403错误 - “CSRF cookie not set”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



问题:



启用CSRF中间件后,Django以AJAX格式请求403回复,说明:


CSRF cookie未设置。


按照文档,实现了一个JS功能,设置自定义X-CSRFToken标题。



它按预期工作,从浏览器获取csrftoken cookie,并发布AJAX请求:

  x-csrftoken:1a0u7GCQG0wepZHQNThIXeYpMy2lZOf2 

但是回复仍然是403。 >

试用的解决方案:



我尝试过在SO或网络上找到的一切,具体地:




  • 检查中间件是否启用:

      MIDDLEWARE_CLASSES = [
    ...
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf .crfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    ...
    ]


  • 启用Cookie的不同浏览器;


  • 使用 @ensure_csrf_cookie装饰我的视图;


  • 在我的模板中设置 {%csrf_token%} / p>


  • 使用 render 快捷方式,它具有正确的请求上下文;


  • 在我的 settings.py中设置自定义 CSRF_COOKIE_NAME CSRF_HEADER_NAME / code>;


  • 明确设置 CSRF_COOKIE_SECURE = False CSRF_COOKIE_HTTPONLY = False ;


  • 明确设置 CSRF_TRUSTED_ORIGINS 设置;


  • 开发和生产服务器测试;


  • 即使 request.META [CSRF_COOKIE_USED] = True 在我看来,正如有人建议的。




仍然没有任何东西。



标题: / p>

如果我使用 @csrf_exempt print(request.META)在我看来,很明显,自定义标头X-CSRFToken存在于请求中,并根据Django文档格式化,使用HTTP_前缀,用下划线替换连字符,全部大写:HTTP_X_CSRFTOKEN



更多的是,它与Django设置的cookie匹配。



Cookie:



奇怪的是,如果我尝试 print(request.COOKIES)在我看来,页面和表单加载我可以看到csrftoken cookie,但AJAX请求上的字典为空。可能是问题吗?



绝望找到实际错误。谢谢你阅读。

解决方案

好的,问题很简单:



默认情况下,Fetch API不发送凭据。根据 MDN


请求界面的凭据只读属性表示
用户代理是否从
中的另一个域发送cookie,交叉-origin请求。这与XHR的
withCredentials标志类似,但有三个可用值。


默认值为省略,它不会发送cookie。您只需在 fetch()函数参数中添加 same-origin

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

你会很好去:)


I've seen a lot about this on SO, but nothing can fix my problem.

Problem:

With CSRF middleware enabled, Django responds with 403 on AJAX form request, stating:

"CSRF cookie not set."

Following the documentation, a JS functionality was implemented, that sets custom "X-CSRFToken" header.

It works as expected, gets "csrftoken" cookie from browser and posts it along with AJAX request:

x-csrftoken: 1a0u7GCQG0wepZHQNThIXeYpMy2lZOf2

But response is still 403.

Tried solutions:

I've tried everything I could find on SO or web, specifically:

  • 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;

  • Decorating my view with @ensure_csrf_cookie;

  • Setting {% csrf_token %} in my template;

  • Using render shortcut which takes right request context;

  • Setting custom CSRF_COOKIE_NAME and CSRF_HEADER_NAME in my settings.py;

  • Explicitly setting CSRF_COOKIE_SECURE = False and CSRF_COOKIE_HTTPONLY = False;

  • Explicitly setting CSRF_TRUSTED_ORIGINS setting;

  • Testing on development and production server;

  • Even request.META["CSRF_COOKIE_USED"] = True in my view, as someone suggested.

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".

Even more, it's value matches with cookie set by Django.

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. 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. According to 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. This is similar to XHR’s withCredentials flag, but with three available values.

Default is omit, and it never sends cookies. You just need to add same-origin to your fetch() function arguments:

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

And you'll be good to go : )

这篇关于Django 1.9 AJAX形式CSRF令牌403错误 - “CSRF cookie not set”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆