简体   繁体   English

在 django rest 框架(使用 TokenAuthentication)公共 APIView 上获取 CSRF 令牌丢失错误

[英]Getting CSRF token missing error on a django rest framework (with TokenAuthentication) public APIView

I'm having issue with Django Rest Framework and CSRF configurations.我遇到了 Django Rest Framework 和 CSRF 配置的问题。 I know there are plenty of similar posts on the subject (like this one Django Rest Framework remove csrf ) but most of them do not apply (I'm not using SessionAuthentication, nor Django templates), and the way DRF handles CSRF is still unclear to me.我知道在这个主题上有很多类似的帖子(比如这个Django Rest Framework remove csrf ),但大多数都不适用(我没有使用 SessionAuthentication,也没有使用 Django 模板),而且 DRF 处理 CSRF 的方式仍然不清楚对我来说。

Here is the situation :这是情况:

  • I have a DRF application acting as a backend API with several routes, with Token Authentication (JWT)我有一个 DRF 应用程序充当后端 API,具有多个路由,带有令牌身份验证 (JWT)
  • I also have a separate frontend communicating with my API.我还有一个单独的前端与我的 API 通信。 Both are on the same domain (say https://example.com and https://example.com/backend )两者都在同一个域中(比如https://example.comhttps://example.com/backend
  • I have a simple APIView on DRF side for registration on which I need to send POST requests.我在 DRF 端有一个简单的APIView用于注册,我需要在其上发送 POST 请求。 This view doesn't require authentication.此视图不需要身份验证。

When I send the POST request, I get a 403 Forbidden error with the following message : detail "CSRF Failed: CSRF token missing or incorrect."当我发送 POST 请求时,我收到403 Forbidden error并显示以下消息: detail "CSRF Failed: CSRF token missing or incorrect."

Here is my view:这是我的观点:

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)

I've read that DRF disables CSRF except for SessionAuthentication which I do not use.我读过 DRF 禁用 CSRF,但我不使用的 SessionAuthentication 除外。 I also read that empty permission_classes should solve most of the problems.我还读到空的permission_classes应该可以解决大部分问题。 So I guess I don't need to add csrf_exempt decorator (which I tried anyway without success btw).所以我想我不需要添加csrf_exempt装饰器(无论如何我都尝试过但没有成功)。

The route declaration in urls.py is the following: urls.py的路由声明如下:

urlpatterns = [
    ...
    path('recaptcha_verify/', RecaptchaVerifyView.as_view(), name='recaptcha_verify'),
    ...
]

Finally, some relevant django settings:最后,一些相关的 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',
    )
}

Also, I'm not sure what to do with settings related to CSRF like SESSION_COOKIE_HTTPONLY , SESSION_COOKIE_SECURE , CSRF_COOKIE_SECURE , SESSION_COOKIE_NAME , CSRF_COOKIE_NAME , even with the CSRF middleware itself.另外,我不确定如何处理与 CSRF 相关的设置,例如SESSION_COOKIE_HTTPONLYSESSION_COOKIE_SECURECSRF_COOKIE_SECURESESSION_COOKIE_NAMECSRF_COOKIE_NAME ,即使是 CSRF 中间件本身。 Whether if I need them or not.无论我是否需要它们。

From what I read so far, I thought I should not bother about CSRF at all since DRF enforces the default Django behaviour, and I'm using TokenAuthentication instead of SessionAuthentication.从我目前读到的内容来看,我认为我根本不应该担心 CSRF,因为 DRF 强制执行默认的 Django 行为,并且我使用的是 TokenAuthentication 而不是 SessionAuthentication。

What am I doing wrong here ?我在这里做错了什么?

PS: I also have another public view (login page) which works fine. PS:我还有另一个公共视图(登录页面),它工作正常。

The key line missing in the setup was authentication_classes = () in addition to the empty permission_classes list.除了空的permission_classes列表之外,设置中缺少的关键行是authentication_classes = ()

So my APIView class now looks like this :所以我的APIView类现在看起来像这样:

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)

And same for the registration view.注册视图也是如此。 Spent hours on this one, but this makes sense now with DRF documentation stating that without explicit declaration of authentication_classes , default SessionAuthentication is enforced thus requires CSRF token.在这个上花了几个小时,但现在 DRF 文档说明没有明确声明authentication_classes ,默认SessionAuthentication被强制执行,因此这需要 CSRF 令牌。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM