Django CSRF check failing with an Ajax POST request

前端 未结 22 1409
佛祖请我去吃肉
佛祖请我去吃肉 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:53

    Use Firefox with Firebug. Open the 'Console' tab while firing the ajax request. With DEBUG=True you get the nice django error page as response and you can even see the rendered html of the ajax response in the console tab.

    Then you will know what the error is.

    0 讨论(0)
  • 2020-11-22 03:53

    I have a solution. in my JS I have two functions. First to get Cookies (ie. csrftoken):

    function getCookie(name) {
    let cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        const cookies = document.cookie.split(';');
        for (let i = 0; i < cookies.length; i++) {
            const 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;
    

    }

    Second one is my ajax function. in this case it's for login and in fact doesn't return any thing, just pass values to set a session:

    function LoginAjax() {
    
    
        //get scrftoken:
        const csrftoken = getCookie('csrftoken');
    
        var req = new XMLHttpRequest();
        var userName = document.getElementById("Login-Username");
        var password = document.getElementById("Login-Password");
    
        req.onreadystatechange = function () {
            if (this.readyState == 4 && this.status == 200) {            
                //read response loggedIn JSON show me if user logged in or not
                var respond = JSON.parse(this.responseText);            
                alert(respond.loggedIn);
    
            }
        }
    
        req.open("POST", "login", true);
    
        //following header set scrftoken to resolve problem
        req.setRequestHeader('X-CSRFToken', csrftoken);
    
        req.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        req.send("UserName=" + userName.value + "&Password=" + password.value);
    }
    
    0 讨论(0)
  • 2020-11-22 03:55

    If you use the $.ajax function, you can simply add the csrf token in the data body:

    $.ajax({
        data: {
            somedata: 'somedata',
            moredata: 'moredata',
            csrfmiddlewaretoken: '{{ csrf_token }}'
        },
    
    0 讨论(0)
  • 2020-11-22 03:55

    The {% csrf_token %} put in html templates inside <form></form>

    translates to something like:

    <input type='hidden' name='csrfmiddlewaretoken' value='Sdgrw2HfynbFgPcZ5sjaoAI5zsMZ4wZR' />
    

    so why not just grep it in your JS like this:

    token = $("#change_password-form").find('input[name=csrfmiddlewaretoken]').val()
    

    and then pass it e.g doing some POST, like:

    $.post( "/panel/change_password/", {foo: bar, csrfmiddlewaretoken: token}, function(data){
        console.log(data);
    });
    
    0 讨论(0)
  • 2020-11-22 03:56

    I've just encountered a bit different but similar situation. Not 100% sure if it'd be a resolution to your case, but I resolved the issue for Django 1.3 by setting a POST parameter 'csrfmiddlewaretoken' with the proper cookie value string which is usually returned within the form of your home HTML by Django's template system with '{% csrf_token %}' tag. I did not try on the older Django, just happened and resolved on Django1.3. My problem was that the first request submitted via Ajax from a form was successfully done but the second attempt from the exact same from failed, resulted in 403 state even though the header 'X-CSRFToken' is correctly placed with the CSRF token value as well as in the case of the first attempt. Hope this helps.

    Regards,

    Hiro

    0 讨论(0)
  • 2020-11-22 03:57

    If someone is strugling with axios to make this work this helped me:

    import axios from 'axios';
    
    axios.defaults.xsrfCookieName = 'csrftoken'
    axios.defaults.xsrfHeaderName = 'X-CSRFToken'
    

    Source: https://cbuelter.wordpress.com/2017/04/10/django-csrf-with-axios/

    0 讨论(0)
提交回复
热议问题