我尝试按下按钮时使用{"detail":"CSRF Failed: CSRF token missing or incorrect."}
命中的API端点。我使用jQuery的ajax方法,并传递了csrf令牌,但收到的错误表明 $('#deactivateBtn').click(function(){
$.ajax({
url: '/api/v1/companies/{{ object.pk }}/',
type: 'PATCH',
contentType: 'application/json',
data: {
'is_active': false,
'csrfmiddlewaretoken': '{{ csrf_token }}'
},
dataType: 'json',
success: function(data){
$('#deactivateBtn').hide();
console.log('hiding');
$('#deactivateSuccess').show();
}
})
});
。
这是我的ajax请求:
django-rest-framework
以及 REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}
的身份验证设置:
ensure_csrf_cookie
尽管在我的ajax请求中传递了令牌,为什么我会收到CSRF错误?我尝试使用来自django.views.decorators.csrf的var re = /\d+\.\d+/g;
var test = "3700 NO LAND VALUE (Lease Property) (0.10)";
var floats = test.match(re);
装饰我的观点,但这似乎无法修复它。
答案 0 :(得分:0)
如果请求方法为POST
且内容类型为multipart/form-data
或application/x-www-form-urlencoded
,Django将仅解析请求正文。在你的例子中,两者都不是,所以Django不会解析正文而无法找到csrf标记。
如果您不想使用具有适当内容类型的POST
请求,则需要将csrf标记传递到X-CsrfToken
标头。该方法适用于任何请求。 Django recommends使用以下代码:
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);
}
}
});
这将确保仅在必要时发送令牌,并且不会意外泄露到恶意站点。
答案 1 :(得分:0)
除@ knbk的答案外,您还需要设置csrftoken
变量
// using jQuery
function getCookie(name) {
var cookieValue = null;
if (document.cookie && document.cookie !== '') {
var cookies = document.cookie.split(';');
for (var i = 0; i < cookies.length; i++) {
var cookie = jQuery.trim(cookies[i]);
// Does this cookie string begin with the name we want?
if (cookie.substring(0, name.length + 1) === (name + '=')) {
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
break;
}
}
}
return cookieValue;
}
var csrftoken = getCookie('csrftoken');
并在您的django-rest-framework
设置文件中:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication', // add this
),
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
答案 2 :(得分:0)
使用已发布的答案的组合结束 - 看起来我需要csrf-token标头,但实际上我可以使用模板标签获取csrf-token:
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", '{{ csrf_token }}');
}
}
});
然后我声明错误的内容类型也存在问题,因此更改为:
// On click of deactivate button, Posting is marked as not active
$('#deactivateBtn').click(function(){
$.ajax({
url: '/api/v1/companies/{{ object.pk }}/',
type: 'PATCH',
data: {
is_active: false
},
success: function(data){
$('#deactivateBtn').hide();
console.log('hiding');
$('#deactivateSuccess').show();
}
})
});
最后,更改了django设置以包含身份验证类:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication',
),
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.IsAuthenticated',
]
}