在 django rest 框架上获取 CSRF 令牌丢失错误(使用 TokenAuthentication)public APIView
Getting CSRF token missing error on a django rest framework (with TokenAuthentication) public APIView
我在使用 Django Rest Framework 和 CSRF 配置时遇到问题。
我知道有很多关于这个主题的类似帖子(比如这篇 ),但其中大部分都不适用(我没有使用 SessionAuthentication,也没有使用 Django 模板),并且 DRF 处理 CSRF 的方式仍然不清楚对我来说。
情况如下:
- 我有一个 DRF 应用程序作为后端 API 有几个路由,带有令牌身份验证 (JWT)
- 我还有一个单独的前端与 API 通信。 两者在同一个域中(比如说https://example.com and https://example.com/backend)
- 我在 DRF 端有一个简单的
APIView
用于注册,我需要在其上发送 POST 请求。此视图不需要身份验证。
当我发送 POST 请求时,我收到带有以下消息的 403 Forbidden error
:
detail "CSRF Failed: CSRF token missing or incorrect."
这是我的观点:
class RecaptchaVerifyView(APIView):
permission_classes = []
serializer_class = ReCaptchaSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
return Response({'success': True}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
我读到 DRF 禁用 CSRF,但我不使用的 SessionAuthentication 除外。我还读到空 permission_classes
应该可以解决大部分问题。所以我想我不需要添加 csrf_exempt
装饰器(顺便说一句,我尝试过但没有成功)。
urls.py
中的路由声明如下:
urlpatterns = [
...
path('recaptcha_verify/', RecaptchaVerifyView.as_view(), name='recaptcha_verify'),
...
]
最后,一些相关的django设置:
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
...
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
此外,我不确定如何处理与 CSRF 相关的设置,例如 SESSION_COOKIE_HTTPONLY
、SESSION_COOKIE_SECURE
、CSRF_COOKIE_SECURE
、SESSION_COOKIE_NAME
、CSRF_COOKIE_NAME
,即使是 CSRF 中间件本身。不管我是否需要它们。
根据我目前所读的内容,我认为我根本不应该为 CSRF 而烦恼,因为 DRF 强制执行默认的 Django 行为,并且我使用的是 TokenAuthentication 而不是 SessionAuthentication。
我做错了什么?
P.S:我还有另一个 public 视图(登录页面),效果很好。
除了空的 permission_classes
列表之外,设置中缺少的关键行是 authentication_classes = ()
。
所以我的 APIView
class 现在看起来像这样:
class RecaptchaVerifyView(APIView):
permission_classes = ()
authentication_classes = ()
@swagger_auto_schema(responses={status.HTTP_200_OK: openapi.Response("")})
def post(self, request, *args, **kwargs):
serializer = ReCaptchaSerializer(data=request.data)
if serializer.is_valid():
return Response({'success': True}, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
注册视图也是如此。花了几个小时在这个上,但是现在 DRF 文档说明没有明确声明 authentication_classes
,默认 SessionAuthentication
是强制执行的,因此这需要 CSRF 令牌。
我在使用 Django Rest Framework 和 CSRF 配置时遇到问题。
我知道有很多关于这个主题的类似帖子(比如这篇
情况如下:
- 我有一个 DRF 应用程序作为后端 API 有几个路由,带有令牌身份验证 (JWT)
- 我还有一个单独的前端与 API 通信。 两者在同一个域中(比如说https://example.com and https://example.com/backend)
- 我在 DRF 端有一个简单的
APIView
用于注册,我需要在其上发送 POST 请求。此视图不需要身份验证。
当我发送 POST 请求时,我收到带有以下消息的 403 Forbidden error
:
detail "CSRF Failed: CSRF token missing or incorrect."
这是我的观点:
class RecaptchaVerifyView(APIView):
permission_classes = []
serializer_class = ReCaptchaSerializer
def post(self, request, *args, **kwargs):
serializer = self.get_serializer(data=request.data)
if serializer.is_valid():
return Response({'success': True}, status=status.HTTP_200_OK)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
我读到 DRF 禁用 CSRF,但我不使用的 SessionAuthentication 除外。我还读到空 permission_classes
应该可以解决大部分问题。所以我想我不需要添加 csrf_exempt
装饰器(顺便说一句,我尝试过但没有成功)。
urls.py
中的路由声明如下:
urlpatterns = [
...
path('recaptcha_verify/', RecaptchaVerifyView.as_view(), name='recaptcha_verify'),
...
]
最后,一些相关的django设置:
MIDDLEWARE = [
"corsheaders.middleware.CorsMiddleware",
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.common.CommonMiddleware",
"django.middleware.csrf.CsrfViewMiddleware",
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
]
...
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework_simplejwt.authentication.JWTAuthentication',
)
}
此外,我不确定如何处理与 CSRF 相关的设置,例如 SESSION_COOKIE_HTTPONLY
、SESSION_COOKIE_SECURE
、CSRF_COOKIE_SECURE
、SESSION_COOKIE_NAME
、CSRF_COOKIE_NAME
,即使是 CSRF 中间件本身。不管我是否需要它们。
根据我目前所读的内容,我认为我根本不应该为 CSRF 而烦恼,因为 DRF 强制执行默认的 Django 行为,并且我使用的是 TokenAuthentication 而不是 SessionAuthentication。
我做错了什么?
P.S:我还有另一个 public 视图(登录页面),效果很好。
除了空的 permission_classes
列表之外,设置中缺少的关键行是 authentication_classes = ()
。
所以我的 APIView
class 现在看起来像这样:
class RecaptchaVerifyView(APIView):
permission_classes = ()
authentication_classes = ()
@swagger_auto_schema(responses={status.HTTP_200_OK: openapi.Response("")})
def post(self, request, *args, **kwargs):
serializer = ReCaptchaSerializer(data=request.data)
if serializer.is_valid():
return Response({'success': True}, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
注册视图也是如此。花了几个小时在这个上,但是现在 DRF 文档说明没有明确声明 authentication_classes
,默认 SessionAuthentication
是强制执行的,因此这需要 CSRF 令牌。