Django Tastypie 总是返回401未授权

1 投票
2 回答
2005 浏览
提问于 2025-04-18 06:38

我正在使用ajax请求来访问我的tastypie资源,但即使我使用了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');
                    }
                });

2 个回答

0

你应该在每次发送POST请求时,把CSRF令牌作为POST数据传递。推荐的CSRF令牌来源是从cookies中获取,像这样:

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

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

撰写回答