【问题标题】:how to pass csrf_token to javascript file in django?如何将 csrf_token 传递给 django 中的 javascript 文件?
【发布时间】:2014-06-14 12:26:51
【问题描述】:

这是我运行良好的 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 文件。我怎样才能让它工作?

【问题讨论】:

    标签: javascript django variables


    【解决方案1】:

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

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

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

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

    【讨论】:

      【解决方案2】:

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

      【讨论】:

        【解决方案3】:

        CSRF 令牌可用作页面上名为“csrftoken”的 cookie。 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) {}
        });
        

        【讨论】:

        【解决方案4】:

        在 Django 2.x 中 参考:https://docs.djangoproject.com/en/2.2/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})
        

        【讨论】:

          【解决方案5】:

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

          【讨论】:

            【解决方案6】:
            <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,
                        },
                        ...
                    })
                    ...
                })
            })
            

            【讨论】:

              【解决方案7】:

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

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

              会有用的

              【讨论】:

                【解决方案8】:

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

                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

                定义函数名称(请求):

                你的功能在这里。

                希望对你有帮助

                【讨论】:

                • 这并不能解决问题 - 它是通过关闭安全功能来避免问题。这就像在说“要修理一个坏了的门铃,把你家的门拆掉,这样人们就不需要再使用门铃了”。
                猜你喜欢
                • 2020-11-20
                • 2012-03-23
                • 2012-01-30
                • 2011-09-22
                • 2019-03-01
                • 2021-10-29
                • 2017-08-17
                • 2023-02-25
                相关资源
                最近更新 更多