Django - CSRF verification failed - send data from

2019-08-23 11:39发布

问题:

My setup:

  • A static website as landing page served via aws S3 (welcome.mydomain.com).
  • A django app (django-1.8 with python 2.7) accessible via a subdomain (app.mydomain.com).

I would like to add a contact form which is part of my static website and which sends the contact form info to my django server to be processed. I do not want to add the contact form as a template to my django app because I am using different style sheets and resources and don't want to mix them between the servers. The view processing the form data is just adding this data to an email and sending this to an internal email address.

I get a 403 csrf verification failed error because the form does not include the csrf token.

I could now exempt the view receiving the request from the csrf verification but I am not sure which security risks this poses.

I am not sure if I am not understanding the csrf attacks and dangers or if I am looking at this problem the wrong way. All my searches and all the answers to django-csrf related questions have not helped me so far.

Here are my questions:

  • Is there a better way to solve this problem?
  • Can I use csrf_exempt without adding any security risks (e.g. by doing extra validations)?

回答1:

You can dynamically add a CSRF token, which is a technique used for ajax requests. From https://docs.djangoproject.com/en/1.11/ref/csrf/:

/**
 * getCookie gets a cookie called 'name' in the current session
 * @param name name of the cookie to get
 * @returns value of the cookie requested, null if not found
 */
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));
}

/**
 * When doing posts, deletes, etc. we need to transmit the CSRF cookie for
 * the request to go through properly, so add the cookie to all ajax calls
 * that need the cookie.
 */
$.ajaxSetup({
    beforeSend: function (xhr, settings) {
        if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

You can then make the 'submit' click on your form post the form data via an ajax call, followed by a redirect to the next page.



回答2:

I would suggest to go through this and decide before you use csrf_exempt decorator provided by django to exempt csrf validation from forms.

What is a CSRF token ? What is its importance and how does it work?

Though nowadays its a good practice to user csrf_token in forms for better security measure.