我正在使用django rest框架browsable api和ModelViewSet来做CRUD操作并且想要使用permissions.IsAuthenticatedOrReadOnly,但是当我登录并尝试DELETE或PUT时我得到
"detail": "CSRF Failed: CSRF token missing or incorrect."
我的观点看起来像这样
class objViewSet(viewsets.ModelViewSet):
queryset = obj.objects.all()
serializer_class = objSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
Settings.py
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
),
Serializer就是
class ObjSerializer(serializers.ModelSerializer):
class Meta:
model = Obj
虽然当我删除permission_classes(所以默认的allowAny触发器)时,我可以正常工作。
我想要什么
只有在我通过身份验证后才能进行PUT / DELETE。我不知道如何自动发送CSRF令牌(modalviewset完成整个工作)
答案 0 :(得分:3)
在REST_FRAMEWORK设置中,您没有提到身份验证方案,因此DRF使用默认身份验证方案SessionAuthentication。此方案强制您将csrf令牌与您的请求放在一起。你可以通过以下方式解决这个问题:
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.BasicAuthentication',
)}
class objViewSet(viewsets.ModelViewSet):
queryset = obj.objects.all()
serializer_class = objSerializer
permission_classes = (permissions.IsAuthenticatedOrReadOnly,)
authentication_classes = (BasicAuthentication,)
来源:http://www.django-rest-framework.org/api-guide/authentication/#sessionauthentication
BTW,csrf令牌被保存为名为“csrftoken”的cookie。您可以从HTTP响应中检索它,并使用键“X-CSRFToken”将其附加到您的请求标头。您可以在https://docs.djangoproject.com/en/dev/ref/csrf/#ajax
上查看有关此内容的详细信息答案 1 :(得分:0)
您可能始终对csrf_token使用SessionAuthentication和会话身份验证检查,您可以通过免除来避免检查,但不要这样做。
我认为您可以保留两个身份验证类。或者只是TokenAuthentication。即,
'DEFAULT_AUTHENTICATION_CLASSES': (
# 'rest_framework.authentication.BasicAuthentication',
'rest_framework.authentication.TokenAuthentication',
'rest_framework.authentication.SessionAuthentication',
# 'oauth2_provider.ext.rest_framework.OAuth2Authentication',
# 'rest_framework_social_oauth2.authentication.SocialAuthentication',
),
如果您不打算使用TokenAuth,只需要会话Auth。你总是可以通过X-CSRFToken标头传递csrf_token。或者你可以去csrf_except的东西。这将避免csrf丢失的问题。
这应该有效。另请参阅以下链接。
答案 2 :(得分:0)
您应该在请求中添加CSRF令牌。如果使用JSON请求执行此操作,则应将此添加到JS代码中。 它从用户cookie中添加CSRF令牌。
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');
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);
}
}
});
答案 3 :(得分:-2)
您可以删除个别网址上的CSRF检查。在你的urls.py上试试这个:
url(r'^/my_url_to_view/', csrf_exempt(views.my_view_function), name='my_name'),