简体   繁体   English

Django:AJAX + CSRF POST产生403

[英]Django: AJAX + CSRF POST gives 403

I have a simple code where I make a POST call to URL in Django with CSRF token included. 我有一个简单的代码,其中包含CSRF令牌的Django对URL进行POST调用。 When I paste the javascript code in the template within <script> tags, it works fine, however as soon as I move the code to a static file, I get HTTP 403 response. 当我将javascript代码粘贴到<script>标记内的模板中时,它可以正常工作,但是,一旦我将代码移动到静态文件中,就会收到HTTP 403响应。 This is strange! 这很奇怪!

Here is the code: 这是代码:

$(document).ready(function() {
    $(".like-button").click(function(event) {
        $.ajax({
            url: <relative path of URL>,
            type: "POST",
            data: {
                csrfmiddlewaretoken: "{{ csrf_token }}",
                // other data items
            },
            success: function(data, textStatus, jqXHR) {},
            error: function(jqXHR, textStatus, errorThrown) {}
        });
        // other javascript code to toggle like button class
    });
});

Here's how I include the static file in Django template: 这是将静态文件包含在Django模板中的方法:

{% block javascript %}
{% load static %}
<script type="text/javascript" src="{% static 'app/app.js' %}"></script>
{% endblock %}

The file is located in static directory: 该文件位于静态目录中:

app
├── static
│   └── app
│       └── app.js

and static settings are: 和静态设置为:

STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(BASE_DIR, 'static')

Note, I do not have STATICFILE_DIRS in the settings yet. 注意,我的设置中还没有STATICFILE_DIRS I can verify that the file is being loaded and executed, since console.log() statements work perfectly fine. 由于console.log()语句工作得很好,因此我可以验证该文件正在加载和执行。 However, I get HTTP 403 request upon POST . 但是,我在POST收到HTTP 403请求。

When you use the tag directly, django processes the templates and replaces csrfmiddlewaretoken: "{{ csrf_token }}" by the correct token. 当您直接使用标签时,django将处理模板,并用正确的令牌替换csrfmiddlewaretoken: "{{ csrf_token }}"

Now, when you use a static file, that variable isn't replaced. 现在,当您使用静态文件时,该变量不会被替换。 In order to add a token you should configure your ajax calls described by django documentation: https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/#ajax 为了添加令牌,您应该配置django文档描述的ajax调用: https : //docs.djangoproject.com/en/1.7/ref/contrib/csrf/#ajax

      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]);
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
              cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
              break;
            }
          }
        }
        return cookieValue;
      }
      var csrftoken = getCookie('csrftoken');
      $.ajaxSetup({
        beforeSend: function(xhr, settings) {
          xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
      });

From Django documentation: 从Django文档中:

NOTE:
The CSRF token is also present in the DOM, but only if explicitly
included using csrf_token in a template. The cookie contains the
canonical token; the CsrfViewMiddleware will prefer the cookie to the
token in the DOM. Regardless, you’re guaranteed to have the cookie if
the token is present in the DOM, so you should use the cookie!

jQuery cookie plugin: jQuery cookie插件:

var csrftoken = $.cookie('csrftoken');

https://docs.djangoproject.com/en/1.7/ref/contrib/csrf/ https://docs.djangoproject.com/zh-CN/1.7/ref/contrib/csrf/

Any static file not rendered directly on the template cannot make use of django's templating engine. 没有直接在模板上呈现的任何静态文件都不能使用django的模板引擎。 You need to use the csrf cookie. 您需要使用csrf cookie。

Check your javascript during runtime, you'll notice the template variable is an empty string. 在运行时检查您的JavaScript,您会注意到template变量是一个空字符串。

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

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