Django CSRF cookie未设置:使用Ajax Cross站点



我的代码有两部分,第一部分是通过简单的python HTTP serverlocalhost:3000上运行的前端(无框架/库)和在localhost:8080上运行的Django server,这里发生的是前台向Django服务器发出跨站点POST请求,但它收到了

Forbidden(未设置CSRF cookie)我没有任何在Django中请求POST调用的经验,不是使用DRF,而是使用我们自己的端点

问题代码:

首先,前端应向/api/csrf/请求csrf令牌

views.py:

def get_csrf(request):
# print(get_token(request))
return JsonResponse({
'detail': 'CSRF cookie set',
'X-CSRFToken': get_token(request)
})

获取值后,令牌通过分配给cookie隐藏元素

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']

现在,每当前端localhost:8080上运行header:{ 'X-CSRFToken': token}的后端进行POST调用时,就会得到Forbidden (CSRF cookie not set.) 403

设置.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

医生说也试试这个:

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);
}
}

但是这里没有成功的尝试,代码出了什么问题?以及我该如何度过难关。

您必须在django-html模板中包含{% csrf_token %}。这将创建名为"csrfmiddlewaretoken"的隐藏输入html标记。

设置var csrftoken = jQuery("[name=csrfmiddlewaretoken]").val();的javascript代码必须在html代码呈现后包含,否则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>

相关内容

  • 没有找到相关文章

最新更新