【问题标题】:CSRF Failed: CSRF token missing or incorrectCSRF 失败:CSRF 令牌丢失或不正确
【发布时间】:2014-12-25 16:16:10
【问题描述】:

我正在使用 Django 1.7 和 django-rest-framework。

我创建了一个 API,它返回一些 JSON 数据,并将其放入我的 settings.py

REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': ('rest_framework.permissions.AllowAny',),
    'DEFAULT_RENDERER_CLASSES': (
    #   'rest_framework.renderers.XMLRenderer',
    'rest_framework.renderers.JSONRenderer',
    #   'rest_framework.renderers.BrowsableAPIRenderer',
    )
}

当我进行 GET 调用时,它会返回所有数据,但是当我尝试使用 PUT/PATCH 时,我会得到:

--------Response Headers---------
Status Code: 403
Date: Wed, 29 Oct 2014 18:51:42 GMT
Vary: Cookie
Server: WSGIServer/0.1 Python/2.7.8
Allow: GET, POST, PUT, PATCH, HEAD, OPTIONS
X-Frame-Options: SAMEORIGIN
Content-Type: application/json
---------------------------------

--------Response Body-----------
{"detail": "CSRF Failed: CSRF token missing or incorrect."}
---------------------------------

这仅在我登录时发生,如果我是匿名的,我可以正确 PUT/PATCH。

我已尝试使用@csrf_exempt,但出现错误,我已将rest_framework.permissions.AllowAny 包含在设置中...

我不知道发生了什么。有谁知道是什么问题?

【问题讨论】:

    标签: django django-rest-framework


    【解决方案1】:

    当您使用SessionAuthentication 时,您使用的是 Django 的身份验证,这通常需要检查 CSRF。 Django REST Framework 强制执行此操作,仅针对 SessionAuthentication,因此您必须在 X-CSRFToken 标头中传递 CSRF 令牌。

    Django documentation 提供了有关使用 jQuery 检索 CSRF 令牌并在请求中发送它的更多信息。 CSRF 令牌保存为一个名为 csrftoken 的 cookie,您可以从 HTTP 响应中检索它,具体取决于所使用的语言。

    如果您无法检索 CSRF cookie,这通常表明您不应该使用 SessionAuthentication。我建议根据您的需要查看TokenAuthenticationOAuth 2.0

    【讨论】:

    • 我知道我应该在通过身份验证时提供 CSRF 令牌,但是,实际上我正在使用 .NET Windows 窗体应用程序与此 API 通信,它通过 HTTPRequest 和 HTTPResponse 方法进行 GET 调用,我不知道在这种情况下如何获得 CSRF 令牌,我没有使用 AJAX 或 HTML 表单。 编辑 .NET 应用程序接收 JSON 格式的纯文本,并返回相同的内容
    • 你没事,我可以使用 cookie 处理 csrftoken 并将其放回标头数据中,这样我就可以在登录时进行 PUT/PATCH 调用。谢谢!
    • @AlexLordMordor 你能解释一下你的解决方案吗?以及为什么当您是登录用户时它不起作用,但以匿名方式起作用。 (我有完全相同的问题)
    • 当您使用 SessionAuthentication 时,默认情况下 django 需要两个“密钥”,其中一个可以在登录用户处于活动状态时在 cookie 中找到,另一个是 csrf-token,如果他们这样做的话不匹配,然后引发错误,因此,有像 @Kevin 这样的文档说要以正确的方式进行身份验证。
    • 另一种实现方式可以在这篇文章中找到:blog.kevinastone.com/…,在“插曲:AngularJS + CSRF 保护”部分。在这种情况下使用 AngularJS
    【解决方案2】:

    这就是我为解决它所做的,我在表单中包含了 csrf 令牌,并在加载文档时使用 jquery/javascrip 得到了这样的 csrf 令牌

    var $crf_token = $('[name="csrfmiddlewaretoken"]').attr('value');
    

    将其包含在 jquery 标头中,如下所示

     $.ajax({
                type: "POST",
                url: "/api/endpoint/",
                data: newEndpoint,
                headers:{"X-CSRFToken": $crf_token},
                success: function (newEnd) {
                    console.log(newEnd);
                    add_end(newEnd);
                },
                error: function () {
                    alert("There was an error")
                }
            });
    

    【讨论】:

    • 这行得通。如果有人想知道,$crf_token 的值来自基本身份验证登录期间拾取的 csrftoken cookie。
    【解决方案3】:

    我认为这是一个 cookie 问题。

    永久解决方案:如果您使用的是 Postman,首先,通过单击“X”清除现有的 cookie。然后添加正确的cookie。

    临时解决方案(用于调试):在您的 settings.py 中试试这个:

    'DEFAULT_AUTHENTICATION_CLASSES': [
        # 'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ]
    

    【讨论】:

    • 清除 cookie 解决了我的问题
    【解决方案4】:

    1- 搜索 Cookie 标头

    2- 将 csrftoken 与 sessionid 分开

    3- 添加 X-CSRFToken={..the csrftoken that you extract in step 2..} 见下文

    4- 再次发帖

    【讨论】:

      【解决方案5】:

      我们遇到了这个问题,结果证明是 Postman 的错。他们自动发送csrftokensessionid 默认值,我们没有在标头中传递这些值。按照本教程帮助解决了这个问题:https://avilpage.com/2019/02/django-tips-csrf-token-postman-curl.html

      【讨论】:

        【解决方案6】:

        解决此错误的最简单方法,我在here 上找到。它非常适合我。

        步骤:

        继承 SessionAuthentication 类:

        from rest_framework.authentication import SessionAuthentication, BasicAuthentication 
        
        class CsrfExemptSessionAuthentication(SessionAuthentication):
        
            def enforce_csrf(self, request):
                return  # To not perform the csrf check previously happening
        

        然后在您创建的 APIView 中,执行以下操作:

        class Object(APIView):
            authentication_classes = (CsrfExemptSessionAuthentication, BasicAuthentication)
        
            def post(self, request, format=None):
        

        这将使您保持登录状态,并且您的 CSRF 令牌将不再检查此 APIView。

        【讨论】:

        • 你已经向 CSRF 攻击敞开了大门。
        【解决方案7】:

        我遇到了类似的问题,我已经将我的网址包装在 csrf_exempt 方法下 -

        from django.views.decorators.csrf import csrf_exempt
        
        url(r'^api/v1/some-resource$', csrf_exempt(SomeApiView.as_view())),
        

        【讨论】:

          【解决方案8】:

          对我有用的最简单的解决方案是:

          在 AJAX POST 调用的标头中添加 CSRF 令牌,这可以通过包含这一行代码来完成

          headers: { "X-CSRFToken": '{{csrf_token}}' },
          

          这行应该加在success上面

          【讨论】:

            【解决方案9】:

            从 cookie 中获取令牌:

            function readCookie(name) {
                var nameEQ = name + "=";
                var ca = document.cookie.split(';');
                for(var i=0;i < ca.length;i++) {
                    var c = ca[i];
                    while (c.charAt(0)==' ') c = c.substring(1,c.length);
                    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
                }
                return null;
            }
            
            var csrftoken = readCookie('csrftoken');
            

            在标头 POST 请求中发送令牌:

              this.$http.post(server,{params: {foo: 'bar'}}, {headers: {"X-CSRFToken":csrftoken }}).then(function (response) {
                        this.response = response.data;
                    },
                    function (response) {
                        console.log(response);
                    });
            

            【讨论】:

            • 这是唯一有实际代码的有效答案。
            【解决方案10】:

            我遇到了类似的问题,我用csrf_exempt 包装了视图,但仍然遇到错误。结果发现我弄错了 URL,所以它被解析为“未找到”回调(CSRF 并没有豁免),因此在我被告知 URL 错误之前抛出了一个异常。

            【讨论】:

            • 对我来说,我只是忘记在我的 URL 中添加结尾的“/”。就像@kokociel 所说,这个问题与 CSRF 无关,而是 URL 没有解析到我的任何端点。
            【解决方案11】:
            // USING AJAX TO UPDATE DATABASE THROUGH REST API
            function getCookie(name) {
                var cookieValue = null;
                if (document.cookie && document.cookie !== '') {
                    var cookies = document.cookie.split(';');
                    for (var i = 0; i < cookies.length; i++) {
                        var cookie = jQuery.trim(cookies[i]);
                        if (cookie.substring(0, name.length + 1) === (name + '=')) {
                            cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                            break;
                        }
                    }
                }
                return cookieValue;
            }
            
            var csrftoken = getCookie('csrftoken');
            
            function csrfSafeMethod(method) {
                // these HTTP methods do not require CSRF protection
                return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
            }
            
            $.ajaxSetup({
                beforeSend: function (xhr, settings) {
                    if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                        xhr.setRequestHeader("X-CSRFToken", csrftoken);
                    }
                }
            });
            

            【讨论】:

              【解决方案12】:

              这发生在我使用邮递员测试 rest-auth 注册时 发生这种情况是因为邮递员发送了错误的标头,一些旧的 cookie 和错误的内容类型,我认为这是某种错误,或者我错了

              解决方案:所以我禁用了默认标题

              手动输入的内容类型和json正文(POST请求)

              然后重新启用所需的标头

              【讨论】:

                【解决方案13】:

                当您在 Apache 服务器上托管 django 网站时。 带有 TokenAuthentication 和 SessionAuthentication 的 Django REST 框架将得到 ​​p>

                CSRF 失败:CSRF 令牌丢失或不正确

                要修复这个打开的 Apache 配置文件 - httpd.conf 添加以下行:

                WSGIPassAuthorization On
                

                【讨论】:

                  【解决方案14】:

                  在settings.py文件中

                  INSTALLED_APPS = [
                  ...
                  ...
                  ...
                  ...
                  'rest_framework.authtoken',
                  ...
                  ]
                  
                  REST_FRAMEWORK = {
                      'DEFAULT_AUTHENTICATION_CLASSES': (
                          'rest_framework.authentication.TokenAuthentication',
                      ),
                  }
                  
                  

                  在项目 urls.py 中

                  from rest_framework.authtoken import views
                  
                  urlpatterns = [
                      ....
                      path('api-token-auth/',views.obtain_auth_token,name='api-token-auth')
                  
                  ]
                  
                  

                  打开终端

                  $ pip3 install httpie
                  $ python3 manage.py createsuperuser # if not created
                  $ http POST http://localhost:8000/api-token-auth/ username="username" password = "password"   # You will get token key (Just copy it) ex:a243re43fdeg7r4rfgedwe89320
                  
                  

                  您的令牌密钥也将自动保存在您的数据库中

                  转到邮递员标题(如示例) 例如:screenshot from postman ,where and how to paste accessed toke

                  然后插入你的令牌密钥。

                  You can take reference to get token key from this video

                  【讨论】:

                    【解决方案15】:

                    我在 postman 中测试 API 时遇到了同样的问题,我通过在 Postman 中为该请求清理缓存解决了这个问题。

                    【讨论】:

                      【解决方案16】:

                      django1.8 python2.7

                      {
                          "detail": "CSRF Failed: CSRF token missing or incorrect."
                      }
                      

                      我通过使用其他 http 方法来修复它; 哦,我又面对了,这次是因为我粘贴了,有一些看不见的字符

                      猜你喜欢
                      • 2014-02-26
                      • 2021-10-01
                      • 2020-09-19
                      • 2021-07-14
                      • 2012-05-16
                      • 2016-12-31
                      • 2011-12-26
                      • 2014-03-29
                      • 1970-01-01
                      相关资源
                      最近更新 更多