2
votes

I have a AJAX process that displays a JSON response. If I disable CSRF protection, the process works. I get HTTP 200 and I get the JSON response.

Following is the working form:

$(document).ready(function() {

    //AJAX
    $('form').on('submit', function(event) {
        $.ajax({
            data : {
                user : $('#user').val(),
                password : $('#password').val()
            },
            url: '/loginproc',
            type: 'POST'
        })
        .done(function(data) {
            if (data.error) {
              $('#errorAlert').text(data.error).show();
              $('#successAlert').hide();
            }
            else {
              $('#successAlert').text(data.xx).show();
              $('#errorAlert').hide();
            }
        });
         event.preventDefault();
    });

});

Is that syntactically correct? Do I need to add a semicolon before ".done"?


I am using Flask-WTForms CSRF protection and the documentation states the following:

When sending an AJAX request, add the X-CSRFToken header to it. For example, in JQuery you can configure all requests to send the token.

<script type="text/javascript">
    var csrf_token = "{{ csrf_token() }}";

    $.ajaxSetup({
        beforeSend: function(xhr, settings) {
            if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrf_token);
            }
        }
    });
</script>

Using the following JS I am able to get the HTTP 200 however, I do not get any JSON data returned

$(document).ready(function() {

    $('form').on('submit', function(event) {

        var csrf_token = "{{ csrf_token() }}";

        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken)
                }
            }
        });

        $.ajax({
            data : {
                user : $('#user').val(),
                password : $('#password').val()
            },
            url: '/loginproc',
            type: 'POST'
        })
        .done(function(data) {
            if (data.error) {
              $('#errorAlert').text(data.error).show();
              $('#successAlert').hide();
            }
            else {
              $('#successAlert').text(data.xx).show();
              $('#errorAlert').hide();
            }
        });
         event.preventDefault();
    });

});

Is that remotely correct? I do get the HTTP 200, but not JSON data returned. JQuery/AJAX has me quite confused.

Questions:

  1. Is form 1 (working form without CSRF) syntactically proper?
  2. Should I not be using "ajaxSetup"?
  3. Any ideas why I am not getting the JSON data back? Do I need to wrap the return in the CSRF too?

Help is greatly appreciated, thank you for your time.

syntactically correct and properly functional 2. s

1
You can enable csrf protection in your htaccess file. Try using the success function instead of done - Brad

1 Answers

0
votes

I reccomend you to move the event.preventDefault(); just after the event submit also use console.log so you can check if the variables contain what you think, the console is in your browser just google how to open your console in your browser so you can check what contains csrf_token and the length and data in the response of "done" aaand add .fail so you can handle server response with errors.

About the question of: 'Do I need to add a semicolon before ".done"?' the answer is no, because that is called method chaining example: $("#id").show().css("background", "red"); in the example im chaining show and css you can chain so many methods at once ;)

$(document).ready(function() {

    $('form').on('submit', function(event) {
        event.preventDefault();
        var csrf_token = "{{ csrf_token() }}";
        console.log("csrf_token: ", csrf_token);

        $.ajaxSetup({
            beforeSend: function(xhr, settings) {
                if (!/^(GET|HEAD|OPTIONS|TRACE)$/i.test(settings.type)) {
                    xhr.setRequestHeader("X-CSRFToken", csrftoken)
                }
            }
        });

        $.ajax({
            data : {
                user : $('#user').val(),
                password : $('#password').val()
            },
            url: '/loginproc',
            type: 'POST'
        })
        .done(function(data) {
            console.log("done", data.length, data); 
            if (data.error) {
              $('#errorAlert').text(data.error).show();
              $('#successAlert').hide();
            }
            else {
              $('#successAlert').text(data.xx).show();
              $('#errorAlert').hide();
            }
        })
        .fail(function( jqXHR, textStatus, errorThrown ) {
            console.error("response with error:", jqXHR, textStatus, errorThrown);
        });             
    });

});