【发布时间】:2021-06-10 12:22:08
【问题描述】:
我的代码有两部分,首先是一个前端(无框架/库),通过简单的python HTTP server 在localhost:3000 上运行,以及在localhost:8080 上运行的Django server,发生了什么这里是前端正在向 Django 服务器发出跨站点 POST 请求,但它得到了 Forbidden (CSRF cookie not set.) 错误。我知道这个问题已经被问过很多次了,但我似乎没有找到解决办法。
我没有任何像这样在 Django 中请求 POST 调用的经验,不是使用 DRF 而是使用我们自己的 endpoints。
问题代码:
首先前端应向/api/csrf/
views.py:
def get_csrf(request):
# print(get_token(request))
return JsonResponse({
'detail': 'CSRF cookie set',
'X-CSRFToken': get_token(request)
})
获取值后,将token分配给cookie和一个隐藏元素 via
main.js:
success: function (response, status, xhr) {
$('.csrftoken').attr('value', response['X-CSRFToken']);
setCookie("csrftoken", response['X-CSRFToken']);
}
上面的代码工作正常,我们得到了值,一开始是这样但没有工作,所以我把它改成这样:
xhr.getResponseHeader("X-CSRFToken") -> response['X-CSRFToken']
现在,每当 frontend 向后端发出 POST 调用,header:{ 'X-CSRFToken': token} 在localhost:8080 上运行,它就会得到Forbidden (CSRF cookie not set.) 403
settings.py
INSTALLED_APPS = [
'corsheaders,
]
MIDDLEWARE = [
'corsheaders.middleware.CorsMiddleware',
]
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_HTTPONLY = True
CORS_ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://127.0.0.1:3000"
]
POST 请求:
$.ajax({
type: "POST",
headers:{
'Content-Type': 'application/json',
'Accept': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
'X-CSRFToken': csrftoken,
},
url: "/api/userdetails/",
data: JSON.stringify(somedata),
...
...
})
到目前为止我所尝试的:
我已尝试通过-
获取 csrftoken# from the hidden element
const csrftoken = document.querySelector('.csrftoken').value;
# from the cookie
const csrftoken = getCCookie('csrftoken');
# from the name
const csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
所有这些都成功检索了值,我可以在请求标头中看到该值,但 django 仍然说没有 csrftoken 正如文档所说,在设置一个必须从隐藏元素中获取值时使用下面的代码,我再次尝试了它以及没有它:
CSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_HTTPONLY = True
Doc 说也试试这个:
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$.ajaxSetup({
beforeSend: function(xhr, settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken", csrftoken);
}
}
但是这里没有成功尝试,代码有什么问题?以及我应该如何度过难关。
【问题讨论】:
-
successfully retrieve the value, but unable to put it in the header请澄清:您的请求中有这个值吗?使用浏览器开发工具检查请求中传递的内容。如果为真,则在您的 settings.py docs.djangoproject.com/en/3.1/ref/settings/#csrf-header-name 中检查此选项值 -
@IvanStarostin 是的,你是对的,值在请求标头中作为 X-CSRFToken 并且 csrf 标头在 settings.py 中设置为默认值,我应该更正问题的那部分。
标签: django ajax csrf http-status-code-403 django-csrf