登录 Django 时 Axios PUT 请求 403 被禁止
Axios PUT Request 403 Forbidden when logged into Django
每当我登录 django 用户并尝试向我的 URL 发送 PUT 请求时,我都会收到 403 禁止错误。但是,它在我未登录时和 Django Rest API 客户端都有效。
这是我的前端代码:
let parameters = `user/${userID}/`
return new Promise((resolve, reject) => {
axios({
method: 'PUT',
url: 'http://127.0.0.1:8000/' + parameters,
data: updatedUser,
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
resolve(response)
})
.catch(error => {
console.log(error)
// reject(error)
})
});
我很困惑,因为当我登录到 django 用户时我看不出区别,当我没有登录时,前端没有任何变化。谢谢
编辑:
这是我的 urls.py
path('user/<id>/', views.RetrieveUpdateDestroyUser.as_view()),
这是视图:
class RetrieveUpdateDestroyUser(RetrieveUpdateDestroyAPIView):
"""
View to handle the retrieving, updating and destroying of a User.
This View will also log any changes made to the model.
"""
serializer_class = UserCreateUpdateSerializer
queryset = CustomUser.objects.all()
lookup_field = 'id'
permission_classes = (AllowAny,)
def update(self, request, *args, **kwargs):
"""
PUT and UPDATE requests handled by this method.
"""
return super().update(request, *args, **kwargs)
我还测试了在登录用户时执行 POST 和 PUT,但它们不起作用,但 GET 可以。谢谢
也尝试禁用 CSRF,但也无济于事
写这个答案是为了总结我们的发现。
问题:对 DRF 端点的 AJAX (PUT) 调用失败,对于经过身份验证的用户出现 403 HTTP 错误,对于匿名用户来说工作正常
期望的行为:使该调用对匿名用户和经过身份验证的用户都有效
原因:默认情况下 DRF 对不安全的 HTTP 方法(POST、PUT、PATCH 和 DELETE)执行 CSRF 检查https://www.django-rest-framework.org/topics/ajax-csrf-cors/
可能的解决方案:
- 按照此处所述禁用 CSRF 检查
- 在 PUT 请求中传递 CSRF 令牌。有关 Django 中 CSRF + AJAX 的更多信息,请阅读此处 https://docs.djangoproject.com/en/3.1/ref/csrf/#ajax。对于 Axios 和 默认 Django 设置,解决方案可能是:
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.withCredentials = true;
每当我登录 django 用户并尝试向我的 URL 发送 PUT 请求时,我都会收到 403 禁止错误。但是,它在我未登录时和 Django Rest API 客户端都有效。
这是我的前端代码:
let parameters = `user/${userID}/`
return new Promise((resolve, reject) => {
axios({
method: 'PUT',
url: 'http://127.0.0.1:8000/' + parameters,
data: updatedUser,
headers: {
'Content-Type': 'application/json',
},
})
.then((response) => {
resolve(response)
})
.catch(error => {
console.log(error)
// reject(error)
})
});
我很困惑,因为当我登录到 django 用户时我看不出区别,当我没有登录时,前端没有任何变化。谢谢
编辑: 这是我的 urls.py
path('user/<id>/', views.RetrieveUpdateDestroyUser.as_view()),
这是视图:
class RetrieveUpdateDestroyUser(RetrieveUpdateDestroyAPIView):
"""
View to handle the retrieving, updating and destroying of a User.
This View will also log any changes made to the model.
"""
serializer_class = UserCreateUpdateSerializer
queryset = CustomUser.objects.all()
lookup_field = 'id'
permission_classes = (AllowAny,)
def update(self, request, *args, **kwargs):
"""
PUT and UPDATE requests handled by this method.
"""
return super().update(request, *args, **kwargs)
我还测试了在登录用户时执行 POST 和 PUT,但它们不起作用,但 GET 可以。谢谢
也尝试禁用 CSRF,但也无济于事
写这个答案是为了总结我们的发现。
问题:对 DRF 端点的 AJAX (PUT) 调用失败,对于经过身份验证的用户出现 403 HTTP 错误,对于匿名用户来说工作正常
期望的行为:使该调用对匿名用户和经过身份验证的用户都有效
原因:默认情况下 DRF 对不安全的 HTTP 方法(POST、PUT、PATCH 和 DELETE)执行 CSRF 检查https://www.django-rest-framework.org/topics/ajax-csrf-cors/
可能的解决方案:
- 按照此处所述禁用 CSRF 检查
- 在 PUT 请求中传递 CSRF 令牌。有关 Django 中 CSRF + AJAX 的更多信息,请阅读此处 https://docs.djangoproject.com/en/3.1/ref/csrf/#ajax。对于 Axios 和 默认 Django 设置,解决方案可能是:
axios.defaults.xsrfHeaderName = "X-CSRFTOKEN";
axios.defaults.xsrfCookieName = "csrftoken";
axios.defaults.withCredentials = true;