Got CSRF verification failure when while requesting POST through API

蹲街弑〆低调 提交于 2019-12-02 21:04:05

问题


I'm writing a site using REST API. I use django with piston at backend (also using corsheaders.middleware.CorsMiddleware with CORS_ORIGIN_ALLOW_ALL = True). And I use backbone.js for frontend. I'm sending POST request from client-side and get error:

CSRF verification failed. Request aborted.

I've googled a lot and all solutions suggested something like "Use the render shortcut which adds RequestContext automatically". But I have no view, forms will be requested from frontend, that shouldn't know about how backend works. Here's code of my scipt

Question = Backbone.Model.extend({
    urlRoot: 'http://example.com/api/questions',

    defaults: {
        id: null,
        title: '',
        text: ''
    },

    initialize: function() {
        //alert(this.title);
    }
});

var question2 = new Question;
var questionDetails = {title: 'test title', text: 'test text'};
question2.save(questionDetails, {
    success: function(question) {
        alert(question.toJSON());
    }
});

回答1:


The django docs have instructions on how to set up jquery to send the csrf token via ajax.

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

You should make sure that the template tag {% csrf_token %} renders something in your frontend. That way you know that the token is being created and passed to the frontend. If you follow the instructions from the docs above then your csrf token should always be sent with ajax requests. This is what the javascript looks like for one of my sites (assuming you are using jQuery).

// Set up Django CSRF Token Protection
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({
    crossDomain: false, // obviates need for sameOrigin test
    beforeSend: function(xhr, settings) {
        if (!csrfSafeMethod(settings.type)) {
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
        }
    }
});

Also, make sure that 'django.middleware.csrf.CsrfViewMiddleware' is in your MIDDLEWARE_CLASSES settings.




回答2:


Sounds like you need to pass the CSRF token through with your save request.

One solution would be to pass the CSRF token back to the model requesting it, then override your model's save method ensuring the model passes the CSRF token back with it.

    Question = Backbone.Model.extend({
        urlRoot: 'http://example.com/api/questions',

        defaults: {
            csrf: null,
            id: null,
            title: '',
            text: ''
        },

        initialize: function() {
            //alert(this.title);
        }

        save: function( data, options ){

             data = $.extend( true, {
               csrf: this.get( 'csrf' )
             }, data );   

             options = _.extend( options, {
                 error: onError,
                 success: onSuccess
              } );

             // Call super method.
             Backbone.Model.prototype.save.apply( this, [ data, options ] );
        }

    });


来源:https://stackoverflow.com/questions/22250944/got-csrf-verification-failure-when-while-requesting-post-through-api

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!