【问题标题】:Django CSRF check failing with an Ajax POST requestDjango CSRF 检查因 Ajax POST 请求而失败
【发布时间】:2011-07-03 07:12:37
【问题描述】:

我可以通过我的 AJAX 帖子使用一些帮助来遵守 Django 的 CSRF 保护机制。我已按照此处的说明进行操作:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/

我已经完全复制了他们在该页面上的 AJAX 示例代码:

http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

我在xhr.setRequestHeader 调用之前放置了一个打印getCookie('csrftoken') 内容的警报,它确实填充了一些数据。我不确定如何验证令牌是否正确,但我很高兴它正在查找和发送某些内容。

但 Django 仍然拒绝我的 AJAX 帖子。

这是我的 JavaScript:

$.post("/memorize/", data, function (result) {
    if (result != "failure") {
        get_random_card();
    }
    else {
        alert("Failed to save card data.");
    }
});

这是我从 Django 看到的错误:

[23/Feb/2011 22:08:29]“POST /memorize/HTTP/1.1”403 2332

我确定我错过了一些东西,也许它很简单,但我不知道它是什么。我搜索了 SO 并看到了一些关于通过 csrf_exempt 装饰器关闭 CSRF 检查我的视图的信息,但我觉得这没有吸引力。我已经尝试过了,它可以工作,但如果可能的话,我宁愿让我的 POST 以 Django 设计的方式工作。

以防万一,这是我的观点的要点:

def myview(request):

    profile = request.user.profile

    if request.method == 'POST':
        """
        Process the post...
        """
        return HttpResponseRedirect('/memorize/')
    else: # request.method == 'GET'

        ajax = request.GET.has_key('ajax')

        """
        Some irrelevent code...
        """

        if ajax:
            response = HttpResponse()
            profile.get_stack_json(response)
            return response
        else:
            """
            Get data to send along with the content of the page.
            """

        return render_to_response('memorize/memorize.html',
                """ My data """
                context_instance=RequestContext(request))

感谢您的回复!

【问题讨论】:

  • 你使用的是什么版本的 django?
  • 你是否添加了正确的 CSRF 中间件类并按正确的顺序放置?
  • Jakub 在下面回答了我的问题,但以防万一它对其他人有用:@zsquare:1.2.3 版。 @mongoose_za:是的,它们是按正确的顺序添加的。

标签: python ajax django csrf


【解决方案1】:

如果你使用$.ajax函数,你可以简单地在数据体中添加csrf标记:

$.ajax({
    data: {
        somedata: 'somedata',
        moredata: 'moredata',
        csrfmiddlewaretoken: '{{ csrf_token }}'
    },

【讨论】:

  • 当我使用标记的答案时,它对我有用,但如果我在这里使用你的解决方案,它不会。但是您的解决方案应该可以工作,但我不明白为什么它不起作用。在 Django 1.4 中还有什么需要做的吗?
  • 谢谢!很简单。仍然适用于 django 1.8 和 jquery 2.1.3
  • 这个解决方案需要将javascript嵌入到模板中是吗?
  • @Mox: 把它放在 html 中,但在你的 Js 文件上方,那里有一个 ajax 函数 <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script>
  • 谢谢兄弟。这是最简单、最干净的解决方案。即使在 Django 3 上也能像魅力一样工作。
【解决方案2】:

真正的解决方案

好的,我设法找到了问题所在。它位于 Javascript(如下所示)代码中。

你需要的是这个:

$.ajaxSetup({ 
     beforeSend: function(xhr, settings) {
         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]);
                     // Does this cookie string begin with the name we want?
                     if (cookie.substring(0, name.length + 1) == (name + '=')) {
                         cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                         break;
                     }
                 }
             }
             return cookieValue;
         }
         if (!(/^http:.*/.test(settings.url) || /^https:.*/.test(settings.url))) {
             // Only send the token to relative URLs i.e. locally.
             xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
         }
     } 
});

而不是官方文档中发布的代码: https://docs.djangoproject.com/en/2.2/ref/csrf/

工作代码来自这个 Django 条目:http://www.djangoproject.com/weblog/2011/feb/08/security/

所以一般的解决方案是:“使用 ajaxSetup 处理程序而不是 ajaxSend 处理程序”。我不知道为什么它有效。但它对我有用:)

以前的帖子(无答案)

我实际上遇到了同样的问题。

它在更新到 Django 1.2.5 后发生 - Django 1.2.4 中的 AJAX POST 请求没有错误(AJAX 没有受到任何保护,但它工作得很好)。

就像 OP 一样,我尝试了 Django 文档中发布的 JavaScript sn-p。我正在使用 jQuery 1.5。我也在使用“django.middleware.csrf.CsrfViewMiddleware”中间件。

我尝试遵循中间件代码,但我知道它在这方面失败了:

request_csrf_token = request.META.get('HTTP_X_CSRFTOKEN', '')

然后

if request_csrf_token != csrf_token:
    return self._reject(request, REASON_BAD_TOKEN)

这个“if”为真,因为“request_csrf_token”为空。

基本上这意味着没有设置标题。那么这个 JS 行有什么问题吗:

xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));

?

我希望提供的详细信息能帮助我们解决问题:)

【讨论】:

  • 这成功了!我在上面粘贴了 .ajaxSetup 函数,现在我可以在没有 403 错误的情况下发布。感谢您分享解决方案,Jakub。很好的发现。 :)
  • 使用 ajaxSetup 而不是 ajaxSend 与 jQuery 文档背道而驰:api.jquery.com/jQuery.ajaxSetup
  • 使用 1.3,官方 django 文档条目对我有用。
  • 我试过了,但这似乎对我不起作用,我使用的是 jQuery v1.7.2,我的问题是stackoverflow.com/questions/11812694/…
  • 我必须在我的视图函数中添加注释 @ensure_csrf_cookie 以在从移动设备请求页面时强制设置 csrf cookie。
【解决方案3】:

将此行添加到您的 jQuery 代码中:

$.ajaxSetup({
  data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
});

完成了。

【讨论】:

  • 我试过这个,除了我的表单有文件上传。我的后端是 django,但仍然收到错误 400 CSRF Failed: CSRF token missing or incorrect.
  • @Hussain 尝试在 html 模板中的某处添加 {% csrf_token %},即使没有表单标签也是如此。没有它,至少对我来说,会发生 403 错误。有关更多信息,请参阅:stackoverflow.com/a/65757544/7076615,我还建议在 Django 中使用 X-editable,它非常好,并且在该线程中是一个完整的示例。
  • 我们如何在 Vanilla JavaScript 中做同样的事情?
【解决方案4】:

{% csrf_token %}&lt;form&gt;&lt;/form&gt;里面放了html模板

翻译成这样的:

<input type='hidden' name='csrfmiddlewaretoken' value='Sdgrw2HfynbFgPcZ5sjaoAI5zsMZ4wZR' />

那么为什么不在你的 JS 中像这样 grep 呢:

token = $("#change_password-form").find('input[name=csrfmiddlewaretoken]').val()

然后传递它,例如做一些 POST,比如:

$.post( "/panel/change_password/", {foo: bar, csrfmiddlewaretoken: token}, function(data){
    console.log(data);
});

【讨论】:

    【解决方案5】:

    问题是因为 django 期望 cookie 中的值作为表单数据的一部分传回。上一个答案中的代码是让 javascript 找出 cookie 值并将其放入表单数据中。从技术角度来看,这是一种很好的方法,但看起来确实有点冗长。

    过去,我通过让 javascript 将令牌值放入帖子数据中来更简单地做到这一点。

    如果您在模板中使用 {% csrf_token %},您将获得一个带有该值的隐藏表单字段。但是,如果你使用 {{ csrf_token }} 你只会得到令牌的裸值,所以你可以像这样在 javascript 中使用它......

    csrf_token = "{{ csrf_token }}";
    

    然后您可以在哈希中包含所需的键名,然后将其作为数据提交给 ajax 调用。

    【讨论】:

    • @aehlke 您可以拥有静态文件。在源代码中,您可以看到一个很好的示例,您可以在 register django variables 对象中使用 window,以便之后可以访问它们。即使在静态文件中。
    • @KitKat 确实 :) 对不起我古老的,无知的评论。好点子。
    • 是静态文件。不是问题,如果你不介意一点点 js 你的 html。我只是将 {{ csrf_token }} 放在主 html 模板中,离 requirejs 咒语不远。像魅力一样工作。
    【解决方案6】:

    非 jquery 答案:

    var csrfcookie = function() {
        var cookieValue = null,
            name = 'csrftoken';
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    };
    

    用法:

    var request = new XMLHttpRequest();
    request.open('POST', url, true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.setRequestHeader('X-CSRFToken', csrfcookie());
    request.onload = callback;
    request.send(data);
    

    【讨论】:

      【解决方案7】:

      似乎没有人提到如何在纯 JS 中使用 X-CSRFToken 标头和 {{ csrf_token }} 执行此操作,所以这里有一个简单的解决方案,您不需要搜索 cookie 或 DOM:

      var xhttp = new XMLHttpRequest();
      xhttp.open("POST", url, true);
      xhttp.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
      xhttp.send();
      

      【讨论】:

        【解决方案8】:

        如果您的表单在没有 JS 的情况下在 Django 中正确发布,您应该能够使用 ajax 逐步增强它,而无需任何黑客或 csrf 令牌的混乱传递。只需序列化整个表单,它将自动获取所有表单字段包括隐藏的 csrf 字段:

        $('#myForm').submit(function(){
            var action = $(this).attr('action');
            var that = $(this);
            $.ajax({
                url: action,
                type: 'POST',
                data: that.serialize()
                ,success: function(data){
                    console.log('Success!');
                }
            });
            return false;
        });
        

        我已经用 Django 1.3+ 和 jQuery 1.5+ 对此进行了测试。显然,这适用于任何 HTML 表单,而不仅仅是 Django 应用程序。

        【讨论】:

          【解决方案9】:

          接受的答案很可能是红鲱鱼。 Django 1.2.4 和 1.2.5 的区别在于 AJAX 请求需要 CSRF 令牌。

          我在 Django 1.3 上遇到了这个问题,它首先是由于没有设置 CSRF cookie。除非必须,否则 Django 不会设置 cookie。因此,在 Django 1.2.4 上运行的专门或大量 ajax 站点可能永远不会向客户端发送令牌,然后需要令牌的升级会导致 403 错误。

          理想的解决方法在这里: http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#page-uses-ajax-without-any-html-form
          但你必须等待 1.4,除非这只是文档赶上代码

          编辑

          还要注意,后来的 Django 文档注意到 jQuery 1.5 中的一个错误,因此请确保您使用 1.5.1 或更高版本以及 Django 建议的代码: https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

          【讨论】:

          • 我的答案在撰写本文时是准确的 :) 就在 Django 从 1.2.4 更新到 1.2.5 之后。也是在最新的 jQuery 版本是 1.5 的时候。事实证明,问题的根源是 jQuery (1.5) 的错误,正如您所说,此信息现在已添加到 Django 文档中。就我而言:设置了 cookie 并且未将令牌添加到 AJAX 请求中。给定的修复适用于有漏洞的 jQuery 1.5。到目前为止,您可以简单地坚持使用官方文档,使用那里给出的示例代码并使用最新的 jQuery。您的问题与此处讨论的问题有不同的来源:)
          • 现在有一个名为 ensure_csrf_cookie 的装饰器,您可以环绕视图以确保它发送 cookie。
          • 这是我遇到的问题,首先没有csrftoken cookie,谢谢!
          【解决方案10】:

          将 Firefox 与 Firebug 一起使用。在触发 ajax 请求时打开“控制台”选项卡。使用DEBUG=True,您将获得漂亮的 django 错误页面作为响应,您甚至可以在控制台选项卡中看到呈现的 ajax 响应的 html。

          那你就知道错误是什么了。

          【讨论】:

            【解决方案11】:

            由于当前答案中的任何地方都没有说明,如果您 不将 js 嵌入到您的模板中,最快的解决方案是:

            &lt;script type="text/javascript"&gt; window.CSRF_TOKEN = "{{ csrf_token }}"; &lt;/script&gt; 放在模板中对script.js 文件的引用之前,然后将csrfmiddlewaretoken 添加到您的js 文件中的data 字典中:

            $.ajax({
                        type: 'POST',
                        url: somepathname + "do_it/",
                        data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
                        success: function() {
                            console.log("Success!");
                        }
                    })
            

            【讨论】:

              【解决方案12】:

              我刚刚遇到了一些不同但相似的情况。不是 100% 确定它是否能解决您的问题,但我通过使用正确的 cookie 值字符串设置 POST 参数“csrfmiddlewaretoken”解决了 Django 1.3 的问题,该字符串通常由 Django 以您的家庭 HTML 的形式返回带有“{% csrf_token %}”标签的模板系统。我没有尝试使用较旧的 Django,只是在 Django1.3 上发生并解决了。 我的问题是,通过 Ajax 从表单提交的第一个请求已成功完成,但来自完全相同的第二次尝试失败,导致 403 状态,即使标题“X-CSRFToken”也正确放置了 CSRF 令牌值就像第一次尝试的情况一样。 希望这会有所帮助。

              问候,

              希罗

              【讨论】:

                【解决方案13】:

                你可以把这个js粘贴到你的html文件中,记得把它放在其他js函数之前

                <script>
                  // using jQuery
                  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]);
                        // Does this cookie string begin with the name we want?
                        if (cookie.substring(0, name.length + 1) == (name + '=')) {
                          cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                          break;
                        }
                      }
                    }
                    return cookieValue;
                  }
                
                  function csrfSafeMethod(method) {
                    // these HTTP methods do not require CSRF protection
                    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
                  }
                
                  $(document).ready(function() {
                    var csrftoken = getCookie('csrftoken');
                    $.ajaxSetup({
                      beforeSend: function(xhr, settings) {
                        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                          xhr.setRequestHeader("X-CSRFToken", csrftoken);
                        }
                      }
                    });
                  });
                </script>
                

                【讨论】:

                • csrftoken 仍然为空。任何想法?抱歉,添加这个,&lt;script type="text/javascript"&gt; window.CSRF_TOKEN = "{{ csrf_token }}"; &lt;/script&gt; 有效
                【解决方案14】:

                使用 Django 轻松调用 ajax

                (26.10.2020)
                在我看来,这比正确答案更清晰、更简单。

                景色

                @login_required
                def some_view(request):
                    """Returns a json response to an ajax call. (request.user is available in view)"""
                    # Fetch the attributes from the request body
                    data_attribute = request.GET.get('some_attribute')  # Make sure to use POST/GET correctly
                    # DO SOMETHING...
                    return JsonResponse(data={}, status=200)
                

                urls.py

                urlpatterns = [
                    path('some-view-does-something/', views.some_view, name='doing-something'),
                ]
                

                ajax 调用

                ajax 调用非常简单,但对于大多数情况来说已经足够了。您可以获取一些值并将它们放入数据对象中,然后在上面描述的视图中您可以通过它们的名称再次获取它们的值。

                您可以在django's documentation 中找到 csrftoken 函数。基本上只需复制它并确保它在您的 ajax 调用之前呈现,以便定义 csrftoken 变量

                $.ajax({
                    url: "{% url 'doing-something' %}",
                    headers: {'X-CSRFToken': csrftoken},
                    data: {'some_attribute': some_value},
                    type: "GET",
                    dataType: 'json',
                    success: function (data) {
                        if (data) {
                            console.log(data);
                            // call function to do something with data
                            process_data_function(data);
                        }
                    }
                });
                

                使用 ajax 将 HTML 添加到当前页面

                这可能有点跑题了,但我很少看到它被使用过,它是最小化窗口重定位以及在 javascript 中手动创建 html 字符串的好方法。

                这与上面的非常相似,但这次我们从响应中渲染 html 而不重新加载当前窗口。

                如果您打算从接收到的数据中呈现某种 html 作为对 ajax 调用的响应,则从视图发送回 HttpResponse 而不是 JsonResponse 可能更容易。这使您可以轻松创建 html,然后可以将其插入到元素中。

                视图

                # The login required part is of course optional
                @login_required
                def create_some_html(request):
                    """In this particular example we are filtering some model by a constraint sent in by 
                    ajax and creating html to send back for those models who match the search"""
                    # Fetch the attributes from the request body (sent in ajax data)
                    search_input = request.GET.get('search_input')
                
                    # Get some data that we want to render to the template
                    if search_input:
                        data = MyModel.objects.filter(name__contains=search_input) # Example
                    else:
                        data = []
                
                    # Creating an html string using template and some data
                    html_response = render_to_string('path/to/creation_template.html', context = {'models': data})
                
                    return HttpResponse(html_response, status=200)
                

                视图的html创建模板

                creation_template.html

                {% for model in models %}
                   <li class="xyz">{{ model.name }}</li>
                {% endfor %}
                

                urls.py

                urlpatterns = [
                    path('get-html/', views.create_some_html, name='get-html'),
                ]
                

                主模板和ajax调用

                这是我们要添加数据的模板。在这个例子中,我们有一个搜索输入和一个将搜索输入的值发送到视图的按钮。然后,视图发送一个 HttpResponse 返回,显示与我们可以在元素内呈现的搜索匹配的数据。

                {% extends 'base.html' %}
                {% load static %}
                {% block content %}
                    <input id="search-input" placeholder="Type something..." value="">
                    <button id="add-html-button" class="btn btn-primary">Add Html</button>
                    <ul id="add-html-here">
                        <!-- This is where we want to render new html -->
                    </ul>
                {% end block %}
                
                {% block extra_js %}
                    <script>
                        // When button is pressed fetch inner html of ul
                        $("#add-html-button").on('click', function (e){
                            e.preventDefault();
                            let search_input = $('#search-input').val();
                            let target_element = $('#add-html-here');
                            $.ajax({
                                url: "{% url 'get-html' %}",
                                headers: {'X-CSRFToken': csrftoken},
                                data: {'search_input': search_input},
                                type: "GET",
                                dataType: 'html',
                                success: function (data) {
                                    if (data) {
                                        /* You could also use json here to get multiple html to
                                        render in different places */
                                        console.log(data);
                                        // Add the http response to element
                                        target_element.html(data);
                                    }
                                }
                            });
                        })
                    </script>
                {% endblock %}
                

                【讨论】:

                  【解决方案15】:

                  在我的情况下,问题在于我从主服务器复制到临时服务器的 nginx 配置,其中禁用了进程中第二个不需要的 https。

                  我不得不在配置中注释掉这两行以使其再次工作:

                  # uwsgi_param             UWSGI_SCHEME    https;
                  # uwsgi_pass_header       X_FORWARDED_PROTO;
                  

                  【讨论】:

                    【解决方案16】:

                    一个 CSRF 令牌分配给每个会话(即每次您登录时)。 因此,在您希望获取用户输入的一些数据并将其作为 ajax 调用发送到受 csrf_protect 装饰器保护的某个函数之前,请尝试在从用户获取此数据之前找到正在调用的函数。例如。必须呈现一些模板,您的用户正在其上输入数据。 该模板正在由某个函数呈现。 在此函数中,您可以获得 csrf 令牌,如下所示: csrf = request.COOKIES['csrftoken'] 现在在上下文字典中传递这个 csrf 值,针对哪个模板正在呈现问题。 现在在该模板中写下这一行: 现在在你的 javascript 函数中,在发出 ajax 请求之前,写下这个: var csrf = $('#csrf').val() 这将选择传递给模板的令牌值并将其存储在变量 csrf 中。 现在,在进行 ajax 调用时,在您的帖子数据中,也传递这个值: “csrfmiddlewaretoken”:csrf

                    即使您没有实现 django 表单,这也可以工作。

                    事实上,这里的逻辑是:你需要可以从请求中获取的令牌。 所以你只需要弄清楚登录后立即调用的函数。一旦你有了这个令牌,要么进行另一个 ajax 调用来获取它,要么将它传递给你的 ajax 可以访问的某个模板。

                    【讨论】:

                    • 结构不是很好,但解释得很好。我的问题是,我以这种方式发送 csrf:csrftoken: csrftoken,而不是 csrfmiddlwaretoken: csrftoken。更改后,它起作用了。谢谢
                    【解决方案17】:

                    对于遇到此问题并尝试调试的人:

                    1) django csrf 检查(假设您要发送一个)是here

                    2) 在我的情况下,settings.CSRF_HEADER_NAME 设置为“HTTP_X_CSRFTOKEN”,而我的 AJAX 调用发送了一个名为“HTTP_X_CSRF_TOKEN”的标头,因此无法正常工作。我可以在 AJAX 调用或 django 设置中更改它。

                    3) 如果您选择在服务器端更改它,请找到您的 django 安装位置并在 csrf middleware 中设置断点。如果您使用的是 virtualenv,它将类似于:~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py

                    import ipdb; ipdb.set_trace() # breakpoint!!
                    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(settings.CSRF_HEADER_NAME, '')
                    

                    然后,确保 csrf 令牌正确来自 request.META

                    4) 如果您需要更改标题等 - 在设置文件中更改该变量

                    【讨论】:

                      【解决方案18】:

                      如果有人正在努力使用 axios 来完成这项工作,这对我有帮助:

                      import axios from 'axios';
                      
                      axios.defaults.xsrfCookieName = 'csrftoken'
                      axios.defaults.xsrfHeaderName = 'X-CSRFToken'
                      

                      来源:https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/

                      【讨论】:

                        【解决方案19】:

                        这是 Django 提供的一个不太冗长的解决方案:

                        <script type="text/javascript">
                        // using jQuery
                        var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
                        
                        function csrfSafeMethod(method) {
                            // these HTTP methods do not require CSRF protection
                            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
                        }
                        // set csrf header
                        $.ajaxSetup({
                            beforeSend: function(xhr, settings) {
                                if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                                    xhr.setRequestHeader("X-CSRFToken", csrftoken);
                                }
                            }
                        });
                        
                        // Ajax call here
                        $.ajax({
                            url:"{% url 'members:saveAccount' %}",
                            data: fd,
                            processData: false,
                            contentType: false,
                            type: 'POST',
                            success: function(data) {
                                alert(data);
                                }
                            });
                        </script>
                        

                        来源:https://docs.djangoproject.com/en/1.11/ref/csrf/

                        【讨论】:

                        • 效果很好!请注意:确保将 Django 表达式标记 {% csrf_token %} 放在
                          元素中,以使 var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val(); 正常工作。另一种获取 csrftoken 的方法:var csrftoken = '{{ csrf_token }}';
                        【解决方案20】:

                        chosen Answer相关,只想添加到所选答案中。

                        在那个答案中,关于.ajaxSetup(...) 的解决方案。在你的 Django settings.py 中,如果你有

                        CSRF_USE_SESSIONS = True
                        

                        这将导致所选答案根本不起作用。在实施所选答案的解决方案时,删除该行或将其设置为 False 对我有用。

                        有趣的是,如果您在 Django settings.py 中设置以下内容

                        CSRF_COOKIE_HTTPONLY = True
                        

                        此变量不会导致所选答案的解决方案停止运行。

                        CSRF_USE_SESSIONSCSRF_COOKIE_HTTPONLY 都来自这个官方的 Django 文档https://docs.djangoproject.com/en/2.2/ref/csrf/

                        (我没有足够的代表发表评论,所以我将我的输入发布为答案)

                        【讨论】:

                          【解决方案21】:

                          我有一个解决方案。在我的 JS 中,我有两个功能。 首先获取Cookies(即csrftoken):

                          function getCookie(name) {
                          let cookieValue = null;
                          if (document.cookie && document.cookie !== '') {
                              const cookies = document.cookie.split(';');
                              for (let i = 0; i < cookies.length; i++) {
                                  const cookie = cookies[i].trim();
                                  // Does this cookie string begin with the name we want?
                                  if (cookie.substring(0, name.length + 1) === (name + '=')) {
                                      cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                                      break;
                                  }
                              }
                          }
                          return cookieValue;
                          

                          }

                          第二个是我的 ajax 函数。在这种情况下,它用于登录,实际上不返回任何内容,只需传递值来设置会话:

                          function LoginAjax() {
                          
                          
                              //get scrftoken:
                              const csrftoken = getCookie('csrftoken');
                          
                              var req = new XMLHttpRequest();
                              var userName = document.getElementById("Login-Username");
                              var password = document.getElementById("Login-Password");
                          
                              req.onreadystatechange = function () {
                                  if (this.readyState == 4 && this.status == 200) {            
                                      //read response loggedIn JSON show me if user logged in or not
                                      var respond = JSON.parse(this.responseText);            
                                      alert(respond.loggedIn);
                          
                                  }
                              }
                          
                              req.open("POST", "login", true);
                          
                              //following header set scrftoken to resolve problem
                              req.setRequestHeader('X-CSRFToken', csrftoken);
                          
                              req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                              req.send("UserName=" + userName.value + "&Password=" + password.value);
                          }
                          

                          【讨论】:

                            【解决方案22】:

                            使用 Django 3.1.1 和我尝试的所有解决方案都失败了。但是,将“csrfmiddlewaretoken”键添加到我的 POST 正文中是有效的。这是我打的电话:

                            $.post(url, {
                              csrfmiddlewaretoken: window.CSRF_TOKEN,
                              method: "POST",
                              data: JSON.stringify(data),
                              dataType: 'JSON',
                            });
                            

                            在 HTML 模板中:

                            <script type="text/javascript">
                              window.CSRF_TOKEN = "{{ csrf_token }}";
                            </script>
                            

                            【讨论】:

                              猜你喜欢
                              • 1970-01-01
                              • 2015-06-21
                              • 1970-01-01
                              • 1970-01-01
                              • 1970-01-01
                              • 2011-07-04
                              • 2013-11-06
                              • 2015-07-02
                              相关资源
                              最近更新 更多