Django Rest Framework,ajax POST有效,但PATCH引发CSRF失败:CSRF令牌丢失或不正确 [英] Django Rest Framework, ajax POST works but PATCH throws CSRF Failed: CSRF token missing or incorrect

查看:119
本文介绍了Django Rest Framework,ajax POST有效,但PATCH引发CSRF失败:CSRF令牌丢失或不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要将我的项目移植到 Django Rest Framework 上,以为我的项目制作一个合适的REST Api,我认为这对设计API并使其健壮性有很大帮助,但我遇到了一个问题:

I am porting my project to Django Rest Framework to make a proper REST Api for my project, I think it helps a lot designing the API and making it robust but I am running into a problem :

我有一个入口模型,并关联了 ListCreateAPIView RetrieveUpdateDestroyAPIView 视图。
我可以通过ajax请求成功发布列表中的新条目实例,并提供 csrfmiddlewaretoken ,就像在常规Django View中一样。

I have a entry model and associated ListCreateAPIView and RetrieveUpdateDestroyAPIView views. I can successfully post a new entry instance in the list through an ajax request and providing the csrfmiddlewaretoken as I would do in regular Django View.

    POST entries/

现在,我正尝试使用相同的 csrfmiddlewaretoken 将补丁应用于现有实例,

Now I am trying to apply a patch to an existing instance using the same csrfmiddlewaretoken like so:

    PATCH entries/3

则响应状态代码为 403 FORBIDDEN vith错误 CSRF失败:CSRF令牌丢失或不正确尽管我在firebux中检查了 csrfmiddlewaretoken 在请求数据中。

The response status code is then 403 FORBIDDEN vith error CSRF Failed: CSRF token missing or incorrect although I checked in firebux that csrfmiddlewaretoken is in the request data.

我没什么错,我无法确定代码在哪里被拒绝。

I don't what is wrong and I cannot find out where in the code is the request rejected.

注意:我可以使用 Django Rest Framework 可浏览的api修补对象。

Note: I can patch the object with the Django Rest Framework browsable api.

我希望有人可以提供帮助。
谢谢。
Olivier

I hope someone can help. Thanks. Olivier

编辑

我正在研究代码以看看发生PATCH请求拒绝的地方,我在 django.middleware.csrt.py 中找到以下内容:

I was digging into the code to see where the rejetion of the PATCH request occurs and I found in django.middleware.csrt.py the following:

        if csrf_token is None: #<--- csrf_token is defined
            # No CSRF cookie. For POST requests, we insist on a CSRF cookie,
            # and in this way we can avoid all CSRF attacks, including login
            # CSRF.
            return self._reject(request, REASON_NO_CSRF_COOKIE)

        # Check non-cookie token for match.
        request_csrf_token = ""
        if request.method == "POST": #<--- This fails but request_csrf_token is in request.DATA
            request_csrf_token = request.POST.get('csrfmiddlewaretoken', '')

        if request_csrf_token == "":
            # Fall back to X-CSRFToken, to make things easier for AJAX,
            # and possible for PUT/DELETE.
            request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

第二个测试失败,因为它不是POST请求,但是所需的信息在request.DATA中。
所以django似乎并不热衷于接受PATCH请求。
您认为什么是解决此问题的最佳方法?

The second test fails because it is not a POST request but the information required is in request.DATA. So it seems that django is not keen to accept PATCH request. What do you think would be the best way to go around this?

您是否建议使用其他身份验证系统(Django-rest-框架文档)?

Would you recommend using a different authentication system (there are some in Django-rest-framework documentation)?

EDIT2

我找到了解决方案:
我观察到可浏览的api实际上正在发送POST请求,但带有参数_method = PATCH,所以我对ajax请求也做了同样的操作,并且效果很好。

I found out a solution: I observed that the browsable api is actually sending a POST request but with a parameter _method="PATCH", so I did the same with my ajax request and it works fine.

我不知道这样做是否正确,欢迎任何反馈和意见!

I don't know if it is the right way to do, any feedback and opinion is welcome!

EDIT3

因此,经过更多阅读后,我发现(我已经知道..)因为某些浏览器不支持PUT,PATCH,DELETE之类的请求,所以要做的是

So, after more reading, I discovered (I already kind of knew..) that because some browsers do not support requests like PUT, PATCH, DELETE, the way to go is to send a post request with X-HTTP-Method-Override in the header.

所以我认为最好的方法是执行以下操作:

So the good way to go I think is to do the following:

$.ajax({
   headers: {
    'X-HTTP-Method-Override': 'PATCH'
   },
   type : "POST",
   ...
});


推荐答案

我最后将其添加为答案。

I finally add this as an answer.

因此,经过更多阅读后,我发现(我已经知道..),因为某些浏览器不支持PUT,PATCH,DELETE之类的请求,所以要做的是

So, after more reading, I discovered (I already kind of knew..) that because some browsers do not support requests like PUT, PATCH, DELETE, the way to go is to send a post request with X-HTTP-Method-Override in the header.

所以我认为最好的方法是执行以下操作:

So the good way to go I think is to do the following:

$.ajax({
    headers: {
        'X-HTTP-Method-Override': 'PATCH'
    },
    type : "POST",
...
});

这篇关于Django Rest Framework,ajax POST有效,但PATCH引发CSRF失败:CSRF令牌丢失或不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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