如何安全设置UserList的权限类并实现仅返回当前用户数据
解决UserList的权限与数据过滤问题
当然可以通过重写get_queryset()方法来实现仅返回当前登录用户数据的需求,这也是Django REST Framework中处理这类数据权限问题的常规操作。下面根据不同业务场景给你具体的实现方案:
场景1:所有登录用户仅能访问自身数据
如果你的需求是不管用户角色,只要登录就只能查看自己的信息,完全看不到其他用户的数据,那可以直接修改get_queryset(),同时调整权限类确保只有登录用户能访问这个端点:
from django.contrib.auth import get_user_model from rest_framework import mixins, generics from rest_framework.permissions import IsAuthenticated class UserList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): serializer_class = UserSerializer permission_classes = [IsAuthenticated] # 只允许登录用户访问 def get(self, request, *args, **kwargs): self.serializer_class = UserGetSerializer return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) def get_queryset(self): # 直接过滤当前登录用户的数据,不用依赖URL里的query参数,更安全 return get_user_model().objects.filter(pk=self.request.user.pk)
这么做的优势:
- 去掉了原来依赖
query_params的逻辑,避免有人通过修改URL参数偷偷获取所有用户数据 - 权限类设为
IsAuthenticated,直接把未登录用户挡在外面 - 从数据集根源上限制了范围,不管后续怎么处理,返回的都只会是当前用户的数据
场景2:管理员能看全量用户,普通用户仅能看自己
如果需要保留管理员查看全部用户的权限,同时限制普通用户只能访问自身数据,那可以在get_queryset()里加个用户角色判断:
from django.contrib.auth import get_user_model from rest_framework import mixins, generics from rest_framework.permissions import IsAuthenticated class UserList(mixins.ListModelMixin, mixins.CreateModelMixin, generics.GenericAPIView): serializer_class = UserSerializer permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): self.serializer_class = UserGetSerializer return self.list(request, *args, **kwargs) def post(self, request, *args, **kwargs): return self.create(request, *args, **kwargs) def get_queryset(self): current_user = self.request.user # 判断当前用户是否是管理员(staff或超级用户) if current_user.is_staff or current_user.is_superuser: return get_user_model().objects.all() else: # 普通用户只返回自己的数据 return get_user_model().objects.filter(pk=current_user.pk)
额外的优化小建议
- 如果你这个视图主要是用来让用户查看自己的信息,其实更推荐用
RetrieveAPIView而不是ListAPIView——因为单个用户的数据是单条记录,用详情视图语义更清晰,代码也更简洁:
from rest_framework import generics class UserProfileView(generics.RetrieveAPIView): serializer_class = UserGetSerializer permission_classes = [IsAuthenticated] def get_object(self): # 直接返回当前登录用户,不用从URL里取pk参数 return self.request.user
- 建议把创建用户和查看用户的逻辑拆成两个独立视图:一个
UserCreateView处理用户注册,一个UserProfileView处理当前用户的信息查看,这样代码职责更单一,后续维护也更方便。
内容的提问来源于stack exchange,提问作者Zhangg
相关产品推荐
相关产品推荐

