简体   繁体   中英

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. 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. 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:

{% 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. I can verify that the file is being loaded and executed, since console.log() statements work perfectly fine. However, I get HTTP 403 request upon POST .

When you use the tag directly, django processes the templates and replaces csrfmiddlewaretoken: "{{ csrf_token }}" by the correct 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

      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:

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:

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

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

Any static file not rendered directly on the template cannot make use of django's templating engine. You need to use the csrf cookie.

Check your javascript during runtime, you'll notice the template variable is an empty string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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