【问题标题】:How to pass Django csrf token in AJAX (without jQuery)如何在 AJAX 中传递 Django csrf 令牌(没有 jQuery)
【发布时间】:2016-08-19 01:15:23
【问题描述】:

基于w3schools ajax example,我正在尝试进行删除调用,然后从表中删除相应的行。这里有很多关于如何使用 JQuery 的答案,但我没有这样做。我找到了this answer,它让我这样写我的 JavaScript:

function deleteFullLicense(rowid, objectid) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (xhttp.readyState == 4 && xhttp.status == 204) {
        row = document.getElementById(rowid);
        row.parentNode.removeChild(row);
      }
      else {
        window.alert("Something went wrong. The delete failed.");
      }
    };
    xhttp.open("POST", "deleteLicense/" + objectid, true);
    xhttp.send({'csrfmiddlewaretoken': '{{ csrf_token }}'});
}

但我收到了Forbidden (CSRF token missing or incorrect.) 消息。我应该如何发送令牌?

【问题讨论】:

  • 你需要将is设置为header。也许这可以帮助你:stackoverflow.com/questions/22063612/…
  • 我尝试将其设置为标题使用:xhttp.setRequestHeader("csrfmiddlewaretoken", '{{ csrf_token }}') 但这没有区别。还有什么需要做的吗?

标签: javascript ajax django


【解决方案1】:

事实证明,如果我将其命名为 X-CSRFToken,它就会起作用。发现了它here if you want to read more

function deleteFullLicense(rowid, objectid) {
    var xhttp = new XMLHttpRequest();
    xhttp.onreadystatechange = function() {
      if (xhttp.readyState == 4 && xhttp.status == 204) {
        row = document.getElementById(rowid);
        row.parentNode.removeChild(row);
      }
    };
    xhttp.open("POST", "deleteLicense/" + objectid, true);
    xhttp.setRequestHeader("X-CSRFToken", '{{ csrf_token }}')
    xhttp.send();
}

【讨论】:

    【解决方案2】:

    标头名称X-CSRFToken实际上来自Django settings.py中的参数CSRF_HEADER_NAME。当接收到前端请求(例如 ajax 调用)时,Django 内部会检查头参数并将X-CSRFToken 转换为HTTP_X_CSRFTOKEN,这是CSRF_HEADER_NAME 的默认值。

    更好的方法是:

    • 转换CSRF_HEADER_NAME的值
    • 将上一步转换后的值渲染到 HTML 模板中
    • 在前端代码(例如 HTML 模板或单独的 js 文件)中,使用该值和 CSRF 令牌在每个 ajax 调用上创建自定义标头以提交表单。

    这是一个简单的例子

    settings.py

    CSRF_HEADER_NAME = "HTTP_ANTI_CSRF_TOKEN"
    

    views.py的视图函数中

    from django.conf import settings
    from django.http.request import HttpHeaders
    
    prefix =  HttpHeaders.HTTP_PREFIX
    converted = settings.CSRF_HEADER_NAME[len(prefix):]
    converted = converted.replace('_','-')
    # so the value HTTP_ANTI_CSRF_TOKEN is converted to ANTI-CSRF-TOKEN,
    return Response(context={'custom_csrf_header_name':converted})
    

    在您的 HTML 模板中(不是好习惯,因为这只是简单的示例)

    <script>
    // Note that the value is 'ANTI-CSRF-TOKEN'. when this header name goes to
    // backend server, Django will internally convert it back to 'HTTP_ANTI_CSRF_TOKEN'
    var custom_csrf_header_name = "{{ custom_csrf_header_name }}";
    
    // the ajax part is almost the same as described in the accepted answer
    ...
    xhttp.setRequestHeader(custom_csrf_header_name, '{{ csrf_token }}')
    ...
    </script>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-17
      • 2014-10-12
      • 2012-01-26
      • 2019-07-18
      • 2018-09-07
      • 1970-01-01
      相关资源
      最近更新 更多