【问题标题】:how can I solve csrf verification failedcsrf验证失败如何解决
【发布时间】:2019-09-15 18:20:03
【问题描述】:

我正在尝试创建将 zip 文件上传到服务器的表单。但是每次我点击提交时,我都会收到CSRF verification failed 错误。这是我的html代码:

<form method="POST" name="form-import-file" enctype="multipart/form-data">
    <div>
        <input type="file" id="file" name="file" accept=".zip"/>
        <input type="submit" value="Upload file">
    </div>
</form>
<div class="url-csrf" data-csrf="{{ csrf_token }}"></div>
<div class="url-import-file" data-url-import-file="{% url 'intent:import_file' %}"></div>

在我的 .js 代码中:

$("form[name='form-import-file']").submit(function(e) {
    var formData = new FormData($(this)[0]);
    alert(formData);
    var json_data = {'csrfmiddlewaretoken' : $('.url-csrf').attr('data-csrf'), 'file': formData };
    $.ajax({
        url: $('.url-import-file').attr('data-url-import-file'),
        type: "POST",
        data: json_data,
        success: function (msg) {
            alert(msg)
        },
        cache: false,
        contentType: false,
        processData: false
    });
   e.preventDefault();
});

【问题讨论】:

  • 您是否尝试像这样添加{{ csrf_token }} &lt;form method="POST" name="form-import-file" enctype="multipart/form-data"&gt;{{ csrf_token }} 而不是在您的表单之外。
  • 是的,但我不断收到同样的错误。禁止。

标签: ajax django django-csrf


【解决方案1】:

{% csrf_token %} 是隐藏输入字段,而不是 value

在 HTML 中

<div id="csrf_token">
    {% csrf_token %}
</div>

在js中

let csrfToken = $("#csrf_token").val();
var json_data = {'csrfmiddlewaretoken' : csrfToken, 'file': formData };

【讨论】:

    【解决方案2】:

    您是否尝试过使用 django doc 提供的基于 cookie 的 CSRF?

    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 = 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;
    }
    var csrftoken = getCookie('csrftoken');
    

    然后在你的json_data中添加'csrfmiddlewaretoken' : csrftoken,

    【讨论】:

      【解决方案3】:

      最好的方法可能是 Django 文档中描述的方法:Cross Site Request Forgery protection

      如果您的CSRF_USE_SESSIONSCSRF_COOKIE_HTTPONLY 设置为False,我建议您创建init.js 文件并始终将其加载到您的基本html 模板中。在这个文件中包含这两个函数:

      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));
      };
      

      要在您的 ajax 请求中包含 CSRF 令牌,请使用以下代码将其包含在请求标头中:

      $(document).ready(function () {
          $.ajaxSetup({
              beforeSend: function(xhr, settings) {
                  if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                      xhr.setRequestHeader("X-CSRFToken", getCookie('csrftoken'));
                  }
              }
          });
      });
      

      如果您愿意,您可以将它包含在您之前创建的init.js 文件中,但它必须在 jQuery 库之后加载。

      如果您将 CSRF_USE_SESSIONSCSRF_COOKIE_HTTPONLY 设置为 True,请将 {% csrf_token %} 添加到您的表单(或 HTML 中的其他位置),从那里读取令牌并将其包含在您的 ajax 请求中,例如像这样:

      var csrftoken = $("[name=csrfmiddlewaretoken]").val();
      $.ajax({
          beforeSend: function(xhr, settings) {
              if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                  xhr.setRequestHeader("X-CSRFToken", csrftoken);
              }
          },
          url: ...
          ...
          ...
      });
      

      【讨论】:

        【解决方案4】:

        一个简单的解决方案是使用ensure_csrf_cookie 在呈现页面的视图中。重要的是,装饰器必须在呈现页面的视图中, 不在接收post 请求的视图中。

        from django.views.decorators.csrf import ensure_csrf_cookie
        
        @ensure_csrf_cookie
        def get_the_page(request):
            return render(request, 'template.html')
        
        

        【讨论】:

        • 您确定导入状态吗?
        • 不,这是一个复制和粘贴错误,我已经编辑了响应
        • 谢谢。我试过了,但我一直收到同样的禁止错误。
        猜你喜欢
        • 1970-01-01
        • 2014-01-09
        • 2012-09-08
        • 2015-06-02
        • 1970-01-01
        • 2019-04-15
        相关资源
        最近更新 更多