Django @csrf_exempt 在 class 视图中不工作
Django @csrf_exempt not working in class View
我在 Django 1.9 中有一个使用 SessionMiddleware 的应用程序。我想在同一个项目中为这个应用程序创建一个 API,但是当执行 POST 请求时,@csrf_exempt 注释不起作用。
我正在执行抛出 Postman 的请求,这是我目前所做的:
settings.py
MIDDLEWARE_CLASSES = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'a9.utils.middleware.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'a9.core.access.middleware.AccessMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}
}
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
)
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
#'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
#'rest_framework.authentication.TokenAuthentication',
)
}
urls.py
urlpatterns = [
url(r'^v1/', include([
url(r'^', include(router.urls)),
url(r'^auth/', MyAuthentication.as_view()),
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
url(r'^admin/', include(admin.site.urls)),
])),
]
views.py
@method_decorator(csrf_exempt, name='dispatch')
class MyAuthentication(TemplateView):
def post(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
在此之后,我总是收到 CSRF 验证失败错误。
我在django-rest-framework的IRC频道问过这个问题,但我仍然没有答案。拜托,任何建议将不胜感激。
您需要在 dispatch
方法中修饰 csrf_exempt
。
class MyView(FormView):
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(MyView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs):
# ....
return super(MyView, self).post(request, *args, **kwargs)
请勿将 csrf_exempt
与 Django REST 框架一起使用。
这不会起作用,因为 SessionAuthentication 无论如何都会强制执行 csrf 检查。
请确保您在 AJAX 请求中使用 csrf 令牌。 Django a comprehensive documentation 关于它
我找到了解决这个问题的方法。您需要创建一个在任何会话中间件之前调用的中间件,然后检查您想要的 urls 或应用程序以豁免 CSRF 令牌验证。所以,代码将是这样的:
settings.py
MIDDLEWARE_CLASSES = [
'api.middleware.DisableCSRF', # custom middleware for API
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'a9.utils.middleware.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'a9.core.access.middleware.AccessMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
urls.py
app_name = "api"
urlpatterns = [
url(r'^v1/', include([
url(r'^', include(router.urls)),
url(r'^auth/', MyAuthentication.as_view()),
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
url(r'^admin/', include(admin.site.urls)),
])),
]
csrf_disable.py
from django.core.urlresolvers import resolve
# django2
class DisableCSRF(object):
"""Middleware for disabling CSRF in an specified app name.
"""
def process_request(self, request):
"""Preprocess the request.
"""
app_name = "api"
if resolve(request.path_info).app_name == app_name:
setattr(request, '_dont_enforce_csrf_checks', True)
else:
pass # check CSRF token validation
这将仅针对特定应用检查 CSRF 令牌或 url 而不会删除所有 CSRF。另外,这是 django-rest-framework 独立的:)
在我的例子中,在 django3.2 中使用 DRF 和基于函数的视图。我必须明确地将 permission_classes
设置为 []
@api_view(["GET"])
@permission_classes([])
def ping(*args, **kwargs):
"""
Used to double check that the api is up an running.
"""
return Response({"msg": "pong"}, status=200)
我相信基于 class 的观点可能与此类似:
class PingView(ListAPIView):
permission_classes = []
pagination_class = None
serializer_class = None
def get(self):
return Response({"msg": "pong"}, status=200)
我在 Django 1.9 中有一个使用 SessionMiddleware 的应用程序。我想在同一个项目中为这个应用程序创建一个 API,但是当执行 POST 请求时,@csrf_exempt 注释不起作用。
我正在执行抛出 Postman 的请求,这是我目前所做的:
settings.py
MIDDLEWARE_CLASSES = [
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'a9.utils.middleware.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'a9.core.access.middleware.AccessMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
OAUTH2_PROVIDER = {
# this is the list of available scopes
'SCOPES': {'read': 'Read scope', 'write': 'Write scope', 'groups': 'Access to your groups'}
}
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = (
'DELETE',
'GET',
'OPTIONS',
'PATCH',
'POST',
'PUT',
)
CORS_ALLOW_HEADERS = (
'accept',
'accept-encoding',
'authorization',
'content-type',
'dnt',
'origin',
'user-agent',
'x-csrftoken',
'x-requested-with',
)
REST_FRAMEWORK = {
# Use Django's standard `django.contrib.auth` permissions,
# or allow read-only access for unauthenticated users.
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly',
#'rest_framework.permissions.IsAuthenticated',
],
'DEFAULT_AUTHENTICATION_CLASSES': (
'oauth2_provider.ext.rest_framework.OAuth2Authentication',
#'rest_framework.authentication.TokenAuthentication',
)
}
urls.py
urlpatterns = [
url(r'^v1/', include([
url(r'^', include(router.urls)),
url(r'^auth/', MyAuthentication.as_view()),
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
url(r'^admin/', include(admin.site.urls)),
])),
]
views.py
@method_decorator(csrf_exempt, name='dispatch')
class MyAuthentication(TemplateView):
def post(self, request, *args, **kwargs):
return HttpResponse('Hello, World!')
在此之后,我总是收到 CSRF 验证失败错误。
我在django-rest-framework的IRC频道问过这个问题,但我仍然没有答案。拜托,任何建议将不胜感激。
您需要在 dispatch
方法中修饰 csrf_exempt
。
class MyView(FormView):
@method_decorator(csrf_exempt)
def dispatch(self, *args, **kwargs):
return super(MyView, self).dispatch(*args, **kwargs)
def post(self, request, *args, **kwargs):
# ....
return super(MyView, self).post(request, *args, **kwargs)
请勿将 csrf_exempt
与 Django REST 框架一起使用。
这不会起作用,因为 SessionAuthentication 无论如何都会强制执行 csrf 检查。
请确保您在 AJAX 请求中使用 csrf 令牌。 Django a comprehensive documentation 关于它
我找到了解决这个问题的方法。您需要创建一个在任何会话中间件之前调用的中间件,然后检查您想要的 urls 或应用程序以豁免 CSRF 令牌验证。所以,代码将是这样的:
settings.py
MIDDLEWARE_CLASSES = [
'api.middleware.DisableCSRF', # custom middleware for API
'corsheaders.middleware.CorsMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.cache.UpdateCacheMiddleware',
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'a9.utils.middleware.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'a9.core.access.middleware.AccessMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.cache.FetchFromCacheMiddleware',
]
urls.py
app_name = "api"
urlpatterns = [
url(r'^v1/', include([
url(r'^', include(router.urls)),
url(r'^auth/', MyAuthentication.as_view()),
url(r'^o/', include('oauth2_provider.urls', namespace='oauth2_provider')),
url(r'^admin/', include(admin.site.urls)),
])),
]
csrf_disable.py
from django.core.urlresolvers import resolve
# django2
class DisableCSRF(object):
"""Middleware for disabling CSRF in an specified app name.
"""
def process_request(self, request):
"""Preprocess the request.
"""
app_name = "api"
if resolve(request.path_info).app_name == app_name:
setattr(request, '_dont_enforce_csrf_checks', True)
else:
pass # check CSRF token validation
这将仅针对特定应用检查 CSRF 令牌或 url 而不会删除所有 CSRF。另外,这是 django-rest-framework 独立的:)
在我的例子中,在 django3.2 中使用 DRF 和基于函数的视图。我必须明确地将 permission_classes
设置为 []
@api_view(["GET"])
@permission_classes([])
def ping(*args, **kwargs):
"""
Used to double check that the api is up an running.
"""
return Response({"msg": "pong"}, status=200)
我相信基于 class 的观点可能与此类似:
class PingView(ListAPIView):
permission_classes = []
pagination_class = None
serializer_class = None
def get(self):
return Response({"msg": "pong"}, status=200)