当我通过ajax调用它时,Django Rest框架用AnonymousUser替换我当前经过身份验证的用户?

时间:2015-05-10 21:21:05

标签: javascript python django django-rest-framework

我试图通过简单的RESTful api和Javascript向Django管理页面添加一些交互式内容。应该很简单,但我面临一个奇怪的问题,即我的每一个javascript请求都返回403授权错误。请注意,这仅适用于js。我可以从浏览器中轻轻点击并完成所有基本的CRUD工作。

代码非常基本。

Javascript

$.ajax({
    xhrFields: {withCredentials: true},
    type: 'PATCH',
    url: 'path/to/my/endpoint,
    data: {
        aParam: someValue,
        'csrfmiddlewaretoken': getCookie('csrftoken')
    },
    success: doSomething,
    error: doSomething
});

Python

class MyObjectDetail(RetrieveUpdateDestroyAPIView):
  queryset = MyObject.objects.all()
  serializer_class = MyObjectSerializer

  authentication_classes = (SessionAuthentication,)
  permission_classes = (IsAuthenticated,)

我最初怀疑会话ID没有被发送,因此这就是为什么一切都因为权限而失败的原因。但是,会话cookie确实是在ajax POST中发送的,并由Django中间件获取。 Django没有任何问题拉我的管理会话。但是,(经过 lot 调试之后),我已经在Django Rest Framework中跟踪用户重写为dispatch方法 - 特别是对self.initialize_request的调用。在该调用返回后,我的管理员用户将被换出其余的一个框架AnonymouseUser

我完全迷失了。我用调试器花了大约2个小时,但仍然不明白我的用户被换出的原因。以前有人遇到过这个吗?我只是做错了吗?

1 个答案:

答案 0 :(得分:0)

403错误的正文应包含一条友好的消息,说明问题所在,我认为在这种情况下你会发现该消息抱怨缺少CSRF令牌。

  

请注意,这仅适用于js。我可以从浏览器中点击网址并完成所有基本的CRUD工作。

JS和浏览器之间只有一些不同的东西,它们都不是由Django REST框架直接引起的。你可能会遇到的是如何在AJAX请求中处理CSRF:the CSRF token should be passed in through a header。现在,这意味着将您的JavaScript更改为

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

function addCsrfToken (xhr, settings) {
    if (!csrfSafeMethod(settings.type)) {
        xhr.setRequestHeader("X-CSRFToken", csrftoken);
    }
}

$.ajax({
    xhrFields: {withCredentials: true},
    type: 'PATCH',
    url: 'path/to/my/endpoint',
    data: {
        aParam: someValue
    },
    success: doSomething,
    error: doSomething,
    beforeSend: addCsrfToken
});

请注意,虽然the Django documentation建议全局设置此标头,但它明确禁止在跨源请求中发送令牌。您在代码中看到(来自withCredentials)您正在访问其他域上的API。

  

Django没有任何问题拉我的管理会话。

这很可能是因为点击浏览器中的页面并不会触发CSRF检查,并且可浏览的API会为您处理CSRF。

  

在该呼叫返回后,我的管理员用户将被换出其余的一个框架AnonymouseUser

Django REST框架仅在一个地方处理匿名用户,that's when authentication fails。因此,虽然您的请求可能通过Django进行身份验证,但它可能无法通过Django REST框架进行身份验证。