ModelViewSet-Django REST框架中的不同身份验证和权限
这个问题类似于这个:,但它对我不起作用 我有以下视图集:ModelViewSet-Django REST框架中的不同身份验证和权限,django,django-rest-framework,Django,Django Rest Framework,这个问题类似于这个:,但它对我不起作用 我有以下视图集: class UserViewSet(viewsets.ModelViewSet): serializer_class = UserSerializer queryset = UserProfile.objects.none() permission_classes = [SpecialPermission] SpecialPermission如下所示: class SpecialPermission(IsAuth
class UserViewSet(viewsets.ModelViewSet):
serializer_class = UserSerializer
queryset = UserProfile.objects.none()
permission_classes = [SpecialPermission]
SpecialPermission如下所示:
class SpecialPermission(IsAuthenticated):
def has_permission(self, request, view):
if request.method == 'POST':
return True
return super().has_permission(request, view)
REST框架设置:
"DEFAULT_AUTHENTICATION_CLASSES": ["backend.api.authentication.ExpiringTokenAuthentication"],
"DEFAULT_PERMISSION_CLASSES": ["rest_framework.permissions.IsAuthenticated"],
我希望每个人都能发布到UserViewSet,但其他方法都需要身份验证。然而,有了上面的代码,我在帖子上得到了一个未经授权的回复
我需要改变什么?我想出来了:让执行身份验证变得懒惰解决了我的问题。现在我可以发布了,但身份验证仍然在需要的所有其他方法上运行
def perform_authentication(self, request):
"""
Perform authentication on the incoming request.
Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
pass
虽然可以做到,但imo的这一要求并不能证明此iVology是合理的,因为与身份验证/用户相关的内容应该是干净和安全的 而是将POST方法从此视图集中提取到它自己的类中
class UserViewSet(mixins.RetrieveModelMixin,
mixins.UpdateModelMixin,
mixins.DestroyModelMixin,
mixins.ListModelMixin,
GenericViewSet):
serializer_class = UserSerializer
queryset = UserProfile.objects.none()
permission_classes = [SpecialPermission]
如果您真的想在这个视图集中禁用身份验证,我建议您这样做
def get_authenticators(self):
if self.action == 'create':
return []
return super().get_authenticators()
这比您的解决方案更明确。您是否尝试过
返回super(SpecialPermission,self)。拥有权限(request,view)
?它甚至不调用has\u权限,它在到达权限之前返回未经授权的权限。您为什么使用queryset=UserProfile.objects.none()
您似乎在使用模型权限,在这里的文档中可能会有帮助。出于安全原因,我使用queryset.none()。我希望每个api点都出现在我的drf路由器中,并具有干净的url结构。我不想为创建一个额外的api端点。虽然我必须承认,从代码的角度来看,它是干净的。但我认为你可以毫无问题地将它插入同一个URL。无论如何,我添加了另一个解决方案。
def get_authenticators(self):
if self.action == 'create':
return []
return super().get_authenticators()