每当我通过 ajax 调用它时,Django Rest 框架会用 AnonymousUser 替换我当前经过身份验证的用户吗?
Django Rest framework replacing my currently authenticated user with AnonymousUser whenever I call it via ajax?
我正在尝试通过简单的 RESTful api 和 Javascript 向 Django 管理页面添加一些交互式内容。应该很简单,但我面临一个奇怪的问题,我从 javascript 发出的每一个请求都返回一个 403
授权错误。请注意,这仅适用于 js。我可以很好地从浏览器中点击 url 并执行所有基本的 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 毫无问题地拉取我的管理会话。但是,(经过 很多 的调试之后)我追踪到用户重写到 Django Rest Framework 中的 dispatch
方法——具体来说,是对 self.initialize_request
的调用.在调用 returns 之后,我的管理员用户被替换为其余框架的 AnonymouseUser
s 之一。
我完全迷路了。我花了大约 2 个小时逐步调试调试器,但仍然不明白为什么我的用户被换出。有没有人遇到过这个?我只是做错了什么吗?
403 错误的 body 应该包含一条友好的消息来解释问题所在,我想在这种情况下你会发现该消息是在抱怨缺少 CSRF 令牌。
Note that this only applies to js. I can hit the url from a browser just fine and do all the basic CRUD stuff.
JS和浏览器只有一点点不同,其中none是Django REST framework直接造成的。您可能遇到的问题是 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 建议全局设置此 header,但它明确禁止在 cross-origin 请求中发送令牌。在您的代码中(从 withCredentials
)看起来您正在访问不同域上的 API。
Django pulls my Admin session with no problems.
这很可能是因为在浏览器中点击页面不会触发 CSRF 检查,可浏览的 API 会为您处理 CSRF。
After that call returns, my Admin user gets swapped out for one of rest Framework's AnonymouseUser
.
Django REST 框架只在一处处理匿名用户,that's when authentication fails。因此,虽然您的请求可能通过 Django 进行了身份验证,但它可能并未通过 Django REST 框架进行身份验证。
我正在尝试通过简单的 RESTful api 和 Javascript 向 Django 管理页面添加一些交互式内容。应该很简单,但我面临一个奇怪的问题,我从 javascript 发出的每一个请求都返回一个 403
授权错误。请注意,这仅适用于 js。我可以很好地从浏览器中点击 url 并执行所有基本的 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 毫无问题地拉取我的管理会话。但是,(经过 很多 的调试之后)我追踪到用户重写到 Django Rest Framework 中的 dispatch
方法——具体来说,是对 self.initialize_request
的调用.在调用 returns 之后,我的管理员用户被替换为其余框架的 AnonymouseUser
s 之一。
我完全迷路了。我花了大约 2 个小时逐步调试调试器,但仍然不明白为什么我的用户被换出。有没有人遇到过这个?我只是做错了什么吗?
403 错误的 body 应该包含一条友好的消息来解释问题所在,我想在这种情况下你会发现该消息是在抱怨缺少 CSRF 令牌。
Note that this only applies to js. I can hit the url from a browser just fine and do all the basic CRUD stuff.
JS和浏览器只有一点点不同,其中none是Django REST framework直接造成的。您可能遇到的问题是 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 建议全局设置此 header,但它明确禁止在 cross-origin 请求中发送令牌。在您的代码中(从 withCredentials
)看起来您正在访问不同域上的 API。
Django pulls my Admin session with no problems.
这很可能是因为在浏览器中点击页面不会触发 CSRF 检查,可浏览的 API 会为您处理 CSRF。
After that call returns, my Admin user gets swapped out for one of rest Framework's
AnonymouseUser
.
Django REST 框架只在一处处理匿名用户,that's when authentication fails。因此,虽然您的请求可能通过 Django 进行了身份验证,但它可能并未通过 Django REST 框架进行身份验证。