Django Rest Framework - 带有身份验证/权限装饰器的 GenericViewSet

标签 django authentication django-rest-framework permissions django-generic-views

目前我对单个实体有一个简单的休息设置,

您可以创建一个对象,您可以通过 id 检索它。

“POST”需要认证/许可,“RETRIEVE”不需要认证/许可。

settings.py(需要每个资源的全局身份验证/权限):

REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': [
        'api.authentication.token_authentication.TokenAuthentication'
    ],
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAuthenticated'
    ]
}

在我的资源中,正确应用了全局身份验证/权限设置,但我想为检索方法生成异常:

我的资源.py:
from django.utils.translation import gettext_lazy as _
from rest_framework import mixins, serializers, viewsets
from rest_framework.decorators import authentication_classes, permission_classes

from api.models import Entity


class EntitySerializer(serializers.ModelSerializer):

    class Meta:
        model = Entity
        fields = [...]
        read_only_fields = [...]


class EntityViewSet(
    mixins.CreateModelMixin,
    mixins.RetrieveModelMixin,
    viewsets.GenericViewSet
):

    queryset = Entity.objects.all()
    serializer_class = EntitySerializer

    @permission_classes([]) # this is ignored ?
    @authentication_classes([]) # this is ignored too ?
    def retrieve(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)

结果:
  • “POST”按预期工作
  • “检索”返回 403 ???

  • 为什么retrieve方法还需要认证,返回403?

    有没有更简单的方法来实现这一点?

    问候和感谢!

    最佳答案

    选项 1。

    将装饰器更改为类属性,只需将 permission_classes 设置为 IsAuthenticatedOrReadOnly .IsAuthenticatedOrReadOnly将允许经过身份验证的用户执行任何请求。只有当请求方法是“安全”方法之一时,才允许对未授权用户的请求;获取、头部或选项。

    from rest_framework.permissions import IsAuthenticatedOrReadOnly
    
    class EntityViewSet(
        mixins.CreateModelMixin,
        mixins.RetrieveModelMixin,
        viewsets.GenericViewSet
    ):
    
        queryset = Entity.objects.all()
        serializer_class = EntitySerializer
        permission_classes = (IsAuthenticatedOrReadOnly,)
    

    选项 2。

    创建您自己的 permission并根据您的需要进行定制。然后,将其设置为类属性。

    示例 permissions.py :
    from rest_framework.permissions import BasePermission
    
    class IsStaff(BasePermission):
        def has_permission(self, request, view):
            return request.user.is_authenticated and request.user.is_staff
    

    您的文件:
    from .permissions import IsStaff
    class EntityViewSet(
        mixins.CreateModelMixin,
        mixins.RetrieveModelMixin,
        viewsets.GenericViewSet
    ):
    
        queryset = Entity.objects.all()
        serializer_class = EntitySerializer
        permission_classes = (IsStaff,)
    

    选项 3。

    覆盖 get_permissions类中的方法。
    from rest_framework.permissions import AllowAny
    
    def get_permissions(self):
        if self.action == 'retrieve':
            return [AllowAny]
        return [IsAuthenticated]
    

    选项 4。

    如果您没有为 retrieve 指定任何权限方法,Django Rest Framework 将应用您在 settings.py 中指定的默认框架。 ,在这种情况下是 IsAuthenticated .你应该做的是,对于retrieve方法,允许任何用户。
    from rest_framework.permissions import AllowAny
    
    @permission_classes([AllowAny])
    def retrieve(self, request, *args, **kwargs):
        return super().retrieve(request, *args, **kwargs)
    

    请注意,当您通过类属性或装饰器设置新的权限类时,您是在告诉 View 忽略设置在 settings.py 上的默认列表。文件。

    不用太担心authentication_classes , 自 AllowAny权限类将允许不受限制的访问,无论请求是经过身份验证还是未经身份验证。

    关于Django Rest Framework - 带有身份验证/权限装饰器的 GenericViewSet,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58904662/

    相关文章:

    javascript - Django 中可修改的项目符号列表

    python - Django中unicode的使用

    python - 如何使用 Django Rest Framework 序列化程序构建我的 JSON 响应?

    django - 使用 SSL、AWS Load Balancer、Nginx 和 Gunicorn 的具有复杂堆栈的 Django Rest Framework 的错误超链接

    python - 为什么 virtualenvwrapper 没有将我的环境位置添加到我的 $PATH

    sql - 根据表值找出哪个模式

    asp.net - .NET Web API + 静态 HTML + JS 的最佳身份验证方式

    authentication - 如何针对单个应用程序对来自不同领域的用户进行身份验证?

    php - 我的登录和注册脚本出现问题

    python-3.x - 如何防止Postman之类的工具访问Django Rest api?并且只能从原生APP访问