Django Tastypie 总是返回 401 未经授权

Posted

技术标签:

【中文标题】Django Tastypie 总是返回 401 未经授权【英文标题】:Django Tastypie always returning 401 unauthorized 【发布时间】:2014-07-03 16:05:27 【问题描述】:

我使用 ajax 请求我的美味派资源,但即使我使用 SessionAuthentication() 和 DjangoAuthorization(),它总是得到 401。

resources.py

class EventsResource(ModelResource):

user = fields.ForeignKey(UserResource, 'user')

    class Meta:
        queryset = Event.objects.all()
        resource_name = 'events'
        filtering = 'start': ALL,
                     'end':ALL
                     
        list_allowed_methods = ['get', 'post','put', 'patch']
        detail_allowed_methods = ['get', 'post', 'put', 'delete']
        authentication = SessionAuthentication()
        authorization = Authorization()
        include_resource_uri = True
        limit = 0
        always_return_data = True

这是一个日历资源,所以我有一个事件模型,我的 ajax 请求在 django-admin 中加载的 javascript 文件中;我还检查了请求标头是否具有 csrf 令牌和会话 ID,但它不起作用。

.ajax(
                    url:  event.resource_uri,
                    dataType: 'json',
                    contentType: 'application/json; encode=UTF-8',
                    type: 'DELETE',
                    success: function () 
                        $calendar.fullCalendar('removeEvents');
                        $calendar.fullCalendar('refetchEvents');
                        $('#modal-confirm').modal('hide');
                        showmsg('Evento eliminato correttamente', 'warning');
                    
                );

【问题讨论】:

【参考方案1】:

您正在使用SessionAuthentication,但没有提供 CSRF 令牌标头(我看到您检查了它,但它没有出现在您的代码中)。

在包含您的 JavaScript 的页面中的某处包含 % csrf_token % 标记,然后修改您的 AJAX 方法以使用 beforeSend 选项设置 X-CSRF-Token 标头:

$.ajax(
    url:  event.resource_uri,
    dataType: 'json',
    contentType: 'application/json; encode=UTF-8',
    type: 'DELETE',
    beforeSend: function(jqXHR) 
        jqXHR.setRequestHeader('X-CSRFToken', $('input[name=csrfmiddlewaretoken]').val());
    ,
    success: function () 
        $calendar.fullCalendar('removeEvents');
        $calendar.fullCalendar('refetchEvents');
        $('#modal-confirm').modal('hide');
        showmsg('Evento eliminato correttamente', 'warning');
    
);

【讨论】:

【参考方案2】:

您应该在每个 POST 请求中将 CSRF 令牌作为 POST 数据传递。 CSRF 令牌的推荐来源来自 cookie,如下所示:

getCookie: function(name) 
    var cookieValue = null;
    if (document.cookie && document.cookie != '') 
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) 
            var cookie = $.trim(cookies[i]);
            if (cookie.substring(0, name.length + 1) == (name + '=')) 
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            
        
    
    return cookieValue;

然后,您将像这样在 AJAX 请求中设置标头:

var csrftoken = this.getCookie('csrftoken');
//Use Setup prior or use the beforeSend on the fly 
/*$.ajaxSetup(
    beforeSend: function(xhr, settings) 
            xhr.setRequestHeader("X-CSRFToken", csrftoken);
    
);*/
$.ajax(
    type: "POST",
    dataType: "json",
    contentType: "application/json",
    url: "/my/uri/",
    data: "any": "thing",
    beforeSend: function(xhr, settings) 
        xhr.setRequestHeader("X-CSRFToken", csrftoken);
    ,
    success: function(data) 
        console.log("Weeey") ;
    
);

参考:https://docs.djangoproject.com/en/1.8/ref/csrf/#ajax

【讨论】:

以上是关于Django Tastypie 总是返回 401 未经授权的主要内容,如果未能解决你的问题,请参考以下文章

Django Tastypie 过滤器 OR 语句

Django/Tastypie - DELETE 请求删除所有内容

Django RESTful API - django-piston 与 django-tastypie

Django-Tastypie 过滤所有字段

如何通知应用程序凭据在 Django/Tastypie/REST 中成功

授权总是返回 401