繁体   English   中英

如何将 csrf_token 传递给 django 中的 javascript 文件?

[英]how to pass csrf_token to javascript file in django?

这是我的 javascript 代码,运行良好。 但我喜欢将 javascript 文件分开,而不是用作内联脚本标签

<script>
    $('.book').click(function() {
         var id= $(this).attr('id');
         data={
              'id':id,
              'csrfmiddlewaretoken':'{{ csrf_token }}',
              };
          $.ajax({
            url: '/post/book/',
            cache:'false',
            dataType:'json',
            type:'POST',
            data:data,
            success: function(data){
               //do something
              else {
                  //do something
              }
            }, 
            error: function(error){
              alert('error; '+ eval(error));
            }
          });
          return false;
      });
     });
</script>

我想将它包含在我的 base.html 中的 custom.js 文件中。 这是

{% load static from staticfiles %}
{% load bootstrap3 %}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">

  <title>{% block title %}{% endblock %}</title>
  {% bootstrap_css %}
  <!-- Optional theme -->
  <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap-theme.min.css">
  <link href="{% static "css/custom.css" %}" rel="stylesheet">
  <!-- Latest compiled and minified JavaScript -->
  <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
  <script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.js"></script>
  <script src="{% static "js/custom.js" %}" ></script>
  <script src="{% static "js/jquery.blockUI.js" %}"></script>
  {% bootstrap_javascript %}
  {% load bootstrap3 %}
{% load static from staticfiles %}
{% block content %} {% endblock %}

我无法将 Django 中当前模板中可用的csrf_token引用到static js文件。 我怎样才能让它工作?

如果您想引用模板标签,那么您需要该文件由 Django 模板化(呈现)。 而且我不建议通过 django 渲染所有静态文件...

您可以将 csrf_token 放在一个全局变量中,然后您可以从脚本访问该变量。 在你的 base.html 中是这样的:

<script>
    var csrftoken = '{{ csrf_token }}';
</script>

或者,您可以从 javascript 文件中的 cookie 中提取 csrftoken。 请参阅此问题以获取解决方案。 该 cookie 称为csrftoken 您可以通过打开开发工具并查看域的 cookie 来查看它。

您可以使用以下函数从客户端的“csrftoken”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;
}

并称之为:

getCookie('csrftoken');

或者您可以简单地在 HTML 模板中定义一个变量并在您的客户端脚本中使用它。

<script>
    var CSRF_TOKEN = '{{ csrf_token }}';
</script>

CSRF 令牌可用作页面上名为“csrftoken”的 cookie。 Django 文档建议获取 cookie 并将其作为X-CSRFToken在 HTTP 请求标头中X-CSRFToken 然后您可以使用@csrf_protect装饰器保护视图。

以下是 AJAX 上的 Django 文档: https : //docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

因此,使用jQuery cookie 插件,您的代码可能如下所示:

$.ajax({
  url: '/post/book/',
  cache: 'false',
  dataType: 'json',
  type: 'POST',
  data: data,
  beforeSend: function(xhr) {
    xhr.setRequestHeader('X-CSRFToken', $.cookie('csrftoken')),
  },
  success: function(data) {},
  error: function(error) {}
});

在 Django 2.x 参考: https : //docs.djangoproject.com/en/2.2/ref/csrf/

这是一个最小的例子。

首先在 html 模板中插入你的 url。

<input type="hidden" id="u_calc" data-url="{% url 'demo:calc' %}"/>

然后,从 cookie 中获取您的 url 和 csrf 令牌。 在ajax请求中使用beforeSend

let u_calc = $("#u_calc").attr("data-url");

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');
function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
function get_result(number) {
    let n = number.val();
    $.ajax({
        beforeSend: function (xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },
        method: "POST",
        type: "POST",
        url: u_calc,
        async: true,
        dataType: "json",
        data: JSON.stringify({'number': n}),
        contentType: "application/json",
        success: function (data) {
            alert(data.result);
        },
    });
}

views.pycalc函数可能看起来像

def calc(request):
    if request.is_ajax() and request.method == "POST":
        data = json.loads(request.body)
        number = int(data["number"])
        return JsonResponse({"result": 2 * number})

你可以像这样传递csrf_token

function deleteAccount(id, name) {
  if (confirm('Do you want to delete ' + name + '?')) {
    $.ajax({
      type: 'post',
      url: url,
      data: 'csrfmiddlewaretoken={{csrf_token}}',
      success: function() {
         window.location.reload(true);
      }
    });
  }
}
<button id="check_button" data-csrf="{{ csrf_token }}">
    button
</button>
$(document).ready(function() {
    $('#check_button').click(async function() {
        await fetch(url, {
            method: 'POST',
            headers: {
                'X-CSRFToken': $(this).data().csrf,
            },
            ...
        })
        ...
    })
})

您可以简单地在 HTML 模板中定义它,例如:

<script>
var CSRF_TOKEN = '{{ csrf_token }}';
</script>

它会工作

我已经尝试了很多方法来解决它,这里是回顾:

  1. 在单独的 js 文件中使用 {{ csrf_token }} 不起作用,您将其嵌入到 django 模板中。

  2. 在您的视图中使用 @csrf_protect 效果不佳,因为它只能保护部分功能。

  3. 正确的实现方法在这里:

    从 django.views.decorators.csrf 导入 csrf_exempt

然后在视图函数之前,使用@csrf_exempt:这里是一个例子

从 django.views.decorators.csrf 导入 csrf_exempt

@csrf_exempt

定义函数名称(请求):

你的功能在这里。

希望有帮助

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM