问题描述
我的代码有两部分,首先是通过简单的 localhost:3000
在 python HTTP server
上运行的前端(无框架/库)和在 Django server
上运行的 localhost:8080
/api/csrf/
,这里发生的事情是前端正在向 Django 服务器发出跨站点 POST 请求,但它被禁止(未设置 CSRF cookie。) > 错误。我知道这个问题已经被问过很多次了,但我似乎没有找到解决方案。
我没有像这样在 Django 中请求 POST 调用的任何经验,不是使用 DRF,而是使用我们自己的端点。
问题代码:
首先前端应向def get_csrf(request):
# print(get_token(request))
return JsonResponse({
'detail': 'CSRF cookie set','X-CSRFToken': get_token(request)
})
views.py:
success: function (response,status,xhr) {
$('.csrftoken').attr('value',response['X-CSRFToken']);
setCookie("csrftoken",response['X-CSRFToken']);
}
得到值后,token被分配给cookie和一个隐藏元素通过
main.js:
xhr.getResponseHeader("X-CSRFToken") -> response['X-CSRFToken']
上面的代码工作正常,我们得到了值,一开始,它是这样的,但不起作用,所以我把它改成了:
header:{ 'X-CSRFToken': token}
现在,每当 前端 向后端发出 POST 调用并在 localhost:8080
上运行 Forbidden (CSRF cookie not set.) 403
时,它都会得到 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"
]
settings.py
$.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),...
...
})
POST 请求:
# 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();
到目前为止我尝试过的:
我尝试通过-
获取csrftokenCSRF_COOKIE_HTTPONLY = True
SESSION_COOKIE_HTTPONLY = True
所有这些都成功检索到值,我可以在请求头标头中看到该值,但 django 仍然说没有 csrftoken 正如文档所说,在设置一个必须从隐藏元素中获取值时使用以下代码时,我再次尝试在没有它的情况下使用它:
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);
}
}
Doc 说也试试这个:
{{1}}
但是这里没有成功的尝试,代码有什么问题?以及我该如何度过难关。
解决方法
您必须在 django html 模板中包含 {% csrf_token %}
。这将创建名为“csrfmiddlewaretoken”的隐藏输入 html 标记。
必须在呈现 html 代码后包含设置 var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
的 javascript 代码,否则 var csrftoken 将设置为 null。
<!DOCTYPE html>
<html>
<body>
<form method="post" action="{% url 'django-view-ajax-handle' %}" id="ajax-function-id" name="ajax-function-name">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
// GET CSRF_TOKEN AFTER HTML
var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();
<script>
function csrfSafeMethod(method) {
// these HTTP methods do not require CSRF protection
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
$(document).ready(function () {
$("#ajax-function-id").submit(function (event) {
$.ajax({
type: "POST",url: $('[name="ajax-function-name"]').attr("action"),beforeSend: function(xhr,settings) {
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
xhr.setRequestHeader("X-CSRFToken",csrftoken);
}
},success: function (data) {
// handle_success
}
});
return false;
});
});
</script>
</body>
</html>