我在使用 DRF SessionAuthentication 和定义为 ModelViewSets 的 View 时遇到问题。 “LoginRequiredMixin”在泛型 View 中工作得很好,但我真的不喜欢那些,因为它们要求我手动定义所有 url 并按正确的顺序设置它们。当 ViewSets 允许您更整齐地定义路线时,这非常乏味。
我尝试按照 Django 文档 authentication login() 使用“@login_required”装饰器,但它不接受它。已尝试在我的 ViewSet 中指定authentication_class SessionAuthentication 但无济于事,遵循这些帖子:
当前 FooBar_views.py 文件。到目前为止,我确保用户通过身份验证的唯一方法是检查其 http 请求 header 中提供的 JWT。
foobar_vews.py 与 ViewSets
# @login_required not being accepted when imported
class FooBarViewSet(viewsets.ModelViewSet):
"""
Foo Bar ViewSet calling various serializers depending on request type (GET, PUT etc.)
"""
# Trying to filter FooBars list by status: Exluding unwanted ones
queryset = FooBar.objects.exclude(status__name = 'SOLD').exclude(status__name = 'DELETED').order_by('id').reverse()
# mapping serializer into the action
serializer_classes = {
'list': FooBarIndexSerializer,
'retrieve': FooBarDetailsSerializer,
'create': FooBarCreateSerializer,
}
# Your default serializer
default_serializer_class = FooBarIndexSerializer
def get_serializer_class(self):
"""
Method to detect request type (GET, PUT etc.) and select corresponding serializer.
"""
return self.serializer_classes.get(self.action, self.default_serializer_class)
# TODO: Move this to the permissions.py file?
def get_permissions(self):
"""
Method to apply permissions depending on request type (GET, PUT etc.)
"""
if self.request.method == 'GET':
return [permissions.DjangoModelPermissionsOrAnonReadOnly()]
elif self.request.method == 'POST':
return [permissions.IsAuthenticated(), IsArtist()]
else: # PUT, PATCH, DELETE
return [permissions.IsAuthenticated(), IsOwner()]
如果使用泛型 View ,我需要定义等效项。可以看出,我不需要添加任何“isAuthenticated”权限类,因为“LoginRequiredMixin”通过检查 sessionId 和 CSRFToken 来检查用户是否已登录。
问题在这里,我需要在url.py文件中手动定义所有对应的url。这是乏味且令人困惑的,因为 FooBarListView 和 FooBarCreateView 通常应该是相同的 url,但请求不同,例如 GET 和 POST。
带有通用 View 的foobar_vews.py
class FooBarListView(LoginRequiredMixin, ListAPIView):
queryset = FooBar.objects.all()
serializer_class = FooBarIndexSerializer
class FooBarDetailView(LoginRequiredMixin, RetrieveAPIView):
queryset = FooBar.objects.all()
serializer_class = FooBarDetailsSerializer
# TODO: Voir pour passer aux modelViews
class FooBarCreateView(LoginRequiredMixin, CreateAPIView):
queryset = FooBar.objects.all()
serializer_class = FooBarCreateSerializer
permission_classes = [IsOwner]
def perform_create(self, serializer):
user=self.request.user
serializer.save(user=user)
class FooBarUpdateDestroyView(LoginRequiredMixin, UpdateDestroyAPIView):
queryset=FooBar.objects.all()
serializer_class = FooBarDetailsSerializer
permission_classes = [IsOwner]
因此,有没有办法检查用户是否在 ViewSets 中被盗,或者我是否被迫使用 JWT 身份验证系统,在客户端保存 token (这是否安全?),并从前端确保对于每个请求,用户都在 header 中提供这些内容?
任何关于如何在 ViewSets 中实现这一点的帮助将不胜感激。
最佳答案
第一件事:您必须了解装饰器
只能在函数上使用,您不能按照您使用它的方式在基于类的 View 中使用它。所以很明显 django View 集不会接受 @login_required
装饰器。
那么问题是,你能修饰类的方法吗?答案是,是。 这是 django 文档 Decorating the class ,它说,
To decorate every instance of a class-based view, you need to decorate the class definition itself. To do this you apply the decorator to the dispatch() method of the class.
A method on a class isn’t quite the same as a standalone function, so you can’t just apply a function decorator to the method – you need to transform it into a method decorator first. The method_decorator decorator transforms a function decorator into a method decorator so that it can be used on an instance method. For example:
class ProtectedView(TemplateView):
template_name = 'secret.html'
@method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super().dispatch(*args, **kwargs)
关于python - Django:ViewSets 不接受登录要求,导致 SessionAuthentication 无用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61656146/