1

I have various ajax views that accept data from jquery and work as follows:

@csrf_exempt
def update_view(request):
    if request.method == 'POST':
        process_data()

My question is, how can I protect these views better? Should I pass something like a token in the ajax request in order to validate that it's a valid call? Otherwise, it seems pretty easy to spoof the above ajax views.

1 Answers1

2

Option 1: Include the following in Django templates that use jquery to submit AJAX data:

<script>

// This ensures that jQuery AJAX functions submit the CSRF token

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]);
            // 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;
}
var csrftoken = getCookie('csrftoken');
function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

</script>

Then you won't need the @csrf_exempt decorator in your view.

Source - https://docs.djangoproject.com/en/dev/ref/csrf/#ajax

Option 2: Ensure your form in the template has a {% csrf_token %} tag:

<form id="form_1" method="POST" action="{% url 'update-view' %}">
  {% csrf_token %}
  {{ form }}
  <button type="submit">Save</button>
</form>

Then use jQuery to handle the form submit event and encode the form elements using the serialise() function.

var thisForm = $( "#form_1" );
thisForm.submit(function( event ) {
  event.preventDefault();
  $.ajax({
    url: thisForm.attr( "action" ),
    type: thisForm.attr( "method" ),
    data: thisForm.serialize()
  })
    .done(function( data ) {
      alert( "Data Saved: " + data );
    });
});

The csrfmiddlewaretoken value will be included with your form data:

MattRowbum
  • 2,162
  • 1
  • 15
  • 20