Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jquery/82.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Jquery Django和Ajax:CSRF令牌尽管已传递,但仍丢失_Jquery_Ajax_Django_Python 3.x - Fatal编程技术网

Jquery Django和Ajax:CSRF令牌尽管已传递,但仍丢失

Jquery Django和Ajax:CSRF令牌尽管已传递,但仍丢失,jquery,ajax,django,python-3.x,Jquery,Ajax,Django,Python 3.x,当按下按钮时,我试图点击我使用django rest framework创建的API端点。我正在使用jQuery的ajax方法,并传递csrf令牌,但收到一个错误,该错误声明为{“detail”:“csrf失败:csrf令牌丢失或不正确”。} 以下是我的ajax请求: $('#deactivateBtn').click(function(){ $.ajax({ url: '/api/v1/companies/{{ object.pk }}/',

当按下按钮时,我试图点击我使用
django rest framework
创建的API端点。我正在使用jQuery的ajax方法,并传递csrf令牌,但收到一个错误,该错误声明为
{“detail”:“csrf失败:csrf令牌丢失或不正确”。}

以下是我的ajax请求:

    $('#deactivateBtn').click(function(){
        $.ajax({
            url: '/api/v1/companies/{{ object.pk }}/',
            type: 'PATCH',
            contentType: 'application/json',
            data: {
                'is_active': false,
                'csrfmiddlewaretoken': '{{ csrf_token }}'
            },
            dataType: 'json',
            success: function(data){
                   $('#deactivateBtn').hide();
                   console.log('hiding');
                   $('#deactivateSuccess').show();
            }
        })
    });
以及我对django rest framework的身份验证设置:

    REST_FRAMEWORK = {
        # Use Django's standard `django.contrib.auth` permissions,
        # or allow read-only access for unauthenticated users.
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ]
    }

尽管在ajax请求中传递了令牌,但为什么会出现CSRF错误?我试着用django.views.decorators.csrf中的
sure\u csrf\u cookie
来装饰我的视图,但这似乎无法解决问题

Django只会在请求方法为
POST
且内容类型为
multipart/form data
application/x-www-form-urlencoded
时解析请求正文。在您的示例中,两者都不是真的,因此Django不会解析主体,也找不到csrf令牌

如果不想使用具有适当内容类型的
POST
请求,则需要将csrf令牌传递到
X-CsrfToken
头中。这种方法适用于任何请求。Django使用以下代码:

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);
        }
    }
});

这将确保令牌仅在必要时发送,并且不会意外泄漏到恶意站点

Django只会在请求方法为
POST
且内容类型为
multipart/form data
application/x-www-form-urlencoded
时解析请求正文。在您的示例中,两者都不是真的,因此Django不会解析主体,也找不到csrf令牌

如果不想使用具有适当内容类型的
POST
请求,则需要将csrf令牌传递到
X-CsrfToken
头中。这种方法适用于任何请求。Django使用以下代码:

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);
        }
    }
});

这将确保令牌仅在必要时发送,并且不会意外泄漏到恶意站点

除了@knbk的答案之外,您还需要将
csrftoken
变量设置为

// using jQuery
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');


除了@knbk的答案之外,您还需要将
csrftoken
变量设置为

// using jQuery
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');


最后使用了发布的答案的组合——看起来我需要csrf令牌头,但实际上我可以使用模板标记获取csrf令牌:

    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", '{{ csrf_token }}');
            }
        }
    });
然后,我声明的内容类型也有一个不正确的问题,因此更改为:

    // On click of deactivate button, Posting is marked as not active
    $('#deactivateBtn').click(function(){
        $.ajax({
            url: '/api/v1/companies/{{ object.pk }}/',
            type: 'PATCH',

            data: {
                is_active: false
            },

            success: function(data){
                   $('#deactivateBtn').hide();
                   console.log('hiding');
                   $('#deactivateSuccess').show();
            }
        })
    });
最后,更改了django设置以包括身份验证类:

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.SessionAuthentication',
        ),
        # Use Django's standard `django.contrib.auth` permissions,
        # or allow read-only access for unauthenticated users.
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ]
    }

最终使用了发布的答案的组合--看起来我需要csrf令牌头,但实际上我可以使用模板标记获取csrf令牌:

    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", '{{ csrf_token }}');
            }
        }
    });
然后,我声明的内容类型也有一个不正确的问题,因此更改为:

    // On click of deactivate button, Posting is marked as not active
    $('#deactivateBtn').click(function(){
        $.ajax({
            url: '/api/v1/companies/{{ object.pk }}/',
            type: 'PATCH',

            data: {
                is_active: false
            },

            success: function(data){
                   $('#deactivateBtn').hide();
                   console.log('hiding');
                   $('#deactivateSuccess').show();
            }
        })
    });
最后,更改了django设置以包括身份验证类:

    REST_FRAMEWORK = {
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.SessionAuthentication',
        ),
        # Use Django's standard `django.contrib.auth` permissions,
        # or allow read-only access for unauthenticated users.
        'DEFAULT_PERMISSION_CLASSES': [
            'rest_framework.permissions.IsAuthenticated',
        ]
    }

请显示相应的视图…请显示相应的视图…谢谢您的回答。不过,我不想使用POST方法,这毫无意义——我不是在创建新项目,而是在编辑现有项目。我将如何使用补丁方法?@orange1很抱歉,这还不清楚。如果不使用具有适当内容类型的POST请求,则需要使用
X-CsrfToken
标题。无论请求方法如何,这都会起作用。谢谢您的回答。不过,我不想使用POST方法,这毫无意义——我不是在创建新项目,而是在编辑现有项目。我将如何使用补丁方法?@orange1很抱歉,这还不清楚。如果不使用具有适当内容类型的POST请求,则需要使用
X-CsrfToken
标题。无论请求方法如何,这都将起作用。