首页 > 解决方案 > Django Rest Framework - @csrf_exempt 不适用于自定义 JWT-HTTPOnly Cookie 身份验证

问题描述

如果这个问题已经发布,请原谅我,我几个小时都找不到解决方案,所以觉得有必要在这里提问。

我正在为 DRF 进行自定义身份验证,其中 JWT 令牌将设置为仅 HTTP cookie,而 CSRF 令牌将设置为简单 cookie,以便我可以使用 JS 读取它并添加到标题中。

所以代码如下。身份验证有效,CSRF 检查仅针对不安全的方法进行,但是现在,csrf_exempt 装饰器不起作用。我已经尝试了几乎所有可能的方法,将它设置为调度方法,其他方法,创建基于 func 的视图并添加到那里,但仍然需要 csrf。我认为在深入研究 Django 源代码之后,我发现问题与我正在调用 process_view 函数并将 callback_view 为 None 因此检查返回错误有关。无论如何,我想知道如何解决这个问题?

import jwt
from rest_framework.authentication import BaseAuthentication
from django.middleware.csrf import CsrfViewMiddleware
from rest_framework import exceptions
from django.conf import settings
from django.contrib.auth import get_user_model


class CSRFCheck(CsrfViewMiddleware):
    def _reject(self, request, reason):
        # Return the failure reason instead of an HttpResponse
        return reason


class MyJWTAuthentication(BaseAuthentication):
    def authenticate(self, request):

        User = get_user_model()
        access_token = request.COOKIES.get("accesstoken")

        if not access_token:
            return None

        try:
            payload = jwt.decode(access_token, settings.SECRET_KEY, algorithms=["HS256"])
        except jwt.ExpiredSignatureError:
            raise exceptions.AuthenticationFailed("Access token expired!")
        except:
            raise exceptions.AuthenticationFailed("Access token invalid!")

        user = User.objects.filter(id=payload["user_id"]).first()
        if user is None:
            raise exceptions.AuthenticationFailed("User not found!")

        if not user.is_active:
            raise exceptions.AuthenticationFailed("User is inactive!")

        self.enforce_csrf(request)
        return (user, None)

    def enforce_csrf(self, request):
        """
        Enforce CSRF validation
        """

        def dummy_get_response(request):
            return None

        check = CSRFCheck(dummy_get_response)

        # populates request.META['CSRF_COOKIE'], which is used in process_view()
        check.process_request(request)
        reason = check.process_view(request, None, (), {})
        if reason:
            # CSRF failed, bail with explicit error message
            raise exceptions.PermissionDenied("CSRF Failed: %s" % reason)

提前致谢!

标签: djangodjango-rest-frameworkcsrf

解决方案


推荐阅读