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

时间:2014-04-28 19:47:01

标签: javascript django variables

这是我的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文件。我怎样才能让它发挥作用?

8 个答案:

答案 0 :(得分:10)

如果要引用模板标记,则需要Django对该文件进行模板化(渲染)。我不建议通过django渲染所有静态文件...

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

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

或者您可以从javascript文件中的cookie中提取csrftoken。有关解决方案,请参阅this question。该cookie名为csrftoken。您可以通过打开开发工具并查看域名的Cookie来查看它。

答案 1 :(得分:4)

您可以使用以下功能从客户端的“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>

答案 2 :(得分:2)

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

这是关于AJAX的Django文档:https://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ajax

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

$.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) {}
});

答案 3 :(得分:1)

您可以像这样传递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);
      }
    });
  }
}

答案 4 :(得分:0)

参考:https://docs.djangoproject.com/en/dev/ref/csrf/

这是一个最小的例子。

先将您的网址插入html模板。

<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.py中,calc函数可能类似于

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

参考:https://docs.djangoproject.com/en/dev/ref/csrf/

答案 5 :(得分:0)

<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,
            },
            ...
        })
        ...
    })
})

答案 6 :(得分:0)

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

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

它将起作用

答案 7 :(得分:-1)

我已经尝试了许多方法来解决它,下面是总结:

  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

def function_name(request):

您的功能在这里。

希望有帮助