You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Rest Framework自定义权限Mixin认证未生效问题求助

解决自定义权限Mixin中request未认证的问题

问题描述

我尝试创建一个用于处理视图额外权限校验的自定义Mixin,以下是我的实现代码:

class ProfilePermissionsRequiredMixin:
    required_permissions = []

    def get_required_permissions(self):
        return self.required_permissions

    def dispatch(self, request, *args, **kwargs):
        # Check if the user is authenticated
        if not request.user.is_authenticated:
            raise PermissionDenied("You must be logged in to access this resource.")

        # Get the user's profile
        profile = request.user.profile

        # Check if the profile has all the required permissions
        if all(profile.has_perm(perm) for perm in self.get_required_permissions()):
            return super().dispatch(request, *args, **kwargs)

        # Return 403 Forbidden if any permission check fails
        raise PermissionDenied("You do not have permission to access this resource.")

目前遇到的问题是:获取到的request未经过认证。我使用了自定义认证类,但该类似乎并未在dispatch方法中生效,请问该如何解决?

解决方案

问题核心是你的Mixin的dispatch方法执行时机错误——自定义认证类的逻辑通常在视图dispatch流程的早期执行,若你的Mixin未让认证流程优先运行,就会导致request.user未被正确处理。

1. 优先执行框架的认证流程(推荐)

如果使用Django REST Framework,先调用父类的dispatch完成认证、权限等前置处理,再执行你的自定义权限校验:

from rest_framework.exceptions import PermissionDenied

class ProfilePermissionsRequiredMixin:
    required_permissions = []

    def get_required_permissions(self):
        return self.required_permissions

    def dispatch(self, request, *args, **kwargs):
        # 先调用父类dispatch完成DRF的认证流程
        response = super().dispatch(request, *args, **kwargs)
        
        # 此时request.user已被认证类处理完毕
        profile = request.user.profile
        if all(profile.has_perm(perm) for perm in self.get_required_permissions()):
            return response
        
        raise PermissionDenied("You do not have permission to access this resource.")

2. 调整Mixin的继承顺序

当视图同时使用多个Mixin时,将认证相关的Mixin(如DRF的AuthenticationMixin)放在你的自定义Mixin之前,确保认证逻辑先执行:

class MyView(AuthenticationMixin, ProfilePermissionsRequiredMixin, APIView):
    authentication_classes = [YourCustomAuthClass]
    required_permissions = ["profile.view"]
    
    # 视图逻辑...

3. 手动触发认证流程(特殊场景)

若必须在自定义逻辑前执行认证,可手动调用认证类的authenticate方法:

def dispatch(self, request, *args, **kwargs):
    # 手动遍历认证类完成认证
    for auth_class in self.authentication_classes:
        auth_instance = auth_class()
        user, auth = auth_instance.authenticate(request)
        if user is not None:
            request.user = user
            request.auth = auth
            break
    
    # 后续执行权限校验
    if not request.user.is_authenticated:
        raise PermissionDenied("You must be logged in to access this resource.")
    
    profile = request.user.profile
    if all(profile.has_perm(perm) for perm in self.get_required_permissions()):
        return super().dispatch(request, *args, **kwargs)
    
    raise PermissionDenied("You do not have permission to access this resource.")

关键注意事项

  • 不要绕开框架认证流程:Django/DRF的认证是dispatch的前置环节,直接判断is_authenticated会跳过框架的认证逻辑。
  • 确认自定义认证类配置正确:检查视图或全局设置中authentication_classes是否指定了你的自定义认证类,且其authenticate方法能正确返回用户实例。

内容的提问来源于stack exchange,提问作者Mohammad Alnahhas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:32:09