Django CSRF check failing with an Ajax POST request

前端 未结 22 1408
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 03:46

I could use some help complying with Django\'s CSRF protection mechanism via my AJAX post. I\'ve followed the directions here:

http://docs.djangoproject.com/en/dev/r

相关标签:
22条回答
  • 2020-11-22 03:59

    It seems nobody has mentioned how to do this in pure JS using the X-CSRFToken header and {{ csrf_token }}, so here's a simple solution where you don't need to search through the cookies or the DOM:

    var xhttp = new XMLHttpRequest();
    xhttp.open("POST", url, true);
    xhttp.setRequestHeader("X-CSRFToken", "{{ csrf_token }}");
    xhttp.send();
    
    0 讨论(0)
  • 2020-11-22 03:59

    for someone who comes across this and is trying to debug:

    1) the django csrf check (assuming you're sending one) is here

    2) In my case, settings.CSRF_HEADER_NAME was set to 'HTTP_X_CSRFTOKEN' and my AJAX call was sending a header named 'HTTP_X_CSRF_TOKEN' so stuff wasn't working. I could either change it in the AJAX call, or django setting.

    3) If you opt to change it server-side, find your install location of django and throw a breakpoint in the csrf middleware.f you're using virtualenv, it'll be something like: ~/.envs/my-project/lib/python2.7/site-packages/django/middleware/csrf.py

    import ipdb; ipdb.set_trace() # breakpoint!!
    if request_csrf_token == "":
        # Fall back to X-CSRFToken, to make things easier for AJAX,
        # and possible for PUT/DELETE.
        request_csrf_token = request.META.get(settings.CSRF_HEADER_NAME, '')
    

    Then, make sure the csrf token is correctly sourced from request.META

    4) If you need to change your header, etc - change that variable in your settings file

    0 讨论(0)
  • 2020-11-22 04:02

    Using Django 3.1.1 and all solutions I tried failed. However, adding the "csrfmiddlewaretoken" key to my POST body worked. Here's the call I made:

    $.post(url, {
      csrfmiddlewaretoken: window.CSRF_TOKEN,
      method: "POST",
      data: JSON.stringify(data),
      dataType: 'JSON',
    });
    

    And in the HTML template:

    <script type="text/javascript">
      window.CSRF_TOKEN = "{{ csrf_token }}";
    </script>
    
    0 讨论(0)
  • 2020-11-22 04:04

    The issue is because django is expecting the value from the cookie to be passed back as part of the form data. The code from the previous answer is getting javascript to hunt out the cookie value and put it into the form data. Thats a lovely way of doing it from a technical point of view, but it does look a bit verbose.

    In the past, I have done it more simply by getting the javascript to put the token value into the post data.

    If you use {% csrf_token %} in your template, you will get a hidden form field emitted that carries the value. But, if you use {{ csrf_token }} you will just get the bare value of the token, so you can use this in javascript like this....

    csrf_token = "{{ csrf_token }}";
    

    Then you can include that, with the required key name in the hash you then submit as the data to the ajax call.

    0 讨论(0)
  • 2020-11-22 04:06

    Non-jquery answer:

    var csrfcookie = function() {
        var cookieValue = null,
            name = 'csrftoken';
        if (document.cookie && document.cookie !== '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = cookies[i].trim();
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    };
    

    usage:

    var request = new XMLHttpRequest();
    request.open('POST', url, true);
    request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
    request.setRequestHeader('X-CSRFToken', csrfcookie());
    request.onload = callback;
    request.send(data);
    
    0 讨论(0)
  • 2020-11-22 04:06

    As it is not stated anywhere in the current answers, the fastest solution if you are not embedding js into your template is:

    Put <script type="text/javascript"> window.CSRF_TOKEN = "{{ csrf_token }}"; </script> before your reference to script.js file in your template, then add csrfmiddlewaretoken into your data dictionary in your js file:

    $.ajax({
                type: 'POST',
                url: somepathname + "do_it/",
                data: {csrfmiddlewaretoken: window.CSRF_TOKEN},
                success: function() {
                    console.log("Success!");
                }
            })
    
    0 讨论(0)
提交回复
热议问题