Django REST Framework基于用户组权限的API访问控制实现问询
如何通过组权限限制Django REST Framework的API访问?
当然可以实现!你现在的问题很明确:只配置了IsAuthenticated权限类——它只负责验证用户是否登录,完全没检查用户所在组的权限。咱们一步步来解决这个问题:
1. 先搞懂核心问题
Django REST Framework(DRF)的permission_classes是按顺序执行校验的,你现在的配置只做了“登录验证”这一步,所以不管用户有没有对应权限,只要登录就能访问API。要实现组权限控制,必须加上权限校验的逻辑。
2. 快速方案:用DRF自带的DjangoModelPermissions
如果你的权限是Django默认生成的模型权限(比如Can add mymodel、Can delete mymodel这类),直接用DRF自带的DjangoModelPermissions就能搞定,它会自动把HTTP方法和模型权限对应起来:
修改你的views.py:
from rest_framework.permissions import IsAuthenticated, DjangoModelPermissions class MyApi(ModelViewSet): permission_classes = (IsAuthenticated, DjangoModelPermissions) queryset = MyModel.objects.all() serializer_class = MyModelSerializer
它的对应逻辑是:
- GET/HEAD/OPTIONS 请求 → 检查
Can view mymodel权限 - POST 请求 → 检查
Can add mymodel权限 - PUT/PATCH 请求 → 检查
Can change mymodel权限 - DELETE 请求 → 检查
Can delete mymodel权限
只要你给用户组分配了对应的权限,这个类会自动校验用户(或用户所在组)是否拥有该权限。
3. 灵活方案:自定义权限类(适配自定义权限)
如果你的权限是自定义的(比如你提到的Can add activity),那可以写一个自定义权限类,精准控制每个HTTP方法对应的权限:
先在permissions.py(可以新建这个文件)里写权限类:
from rest_framework import permissions class GroupBasedPermission(permissions.BasePermission): def has_permission(self, request, view): # 先确保用户已登录 if not request.user.is_authenticated: return False # 定义HTTP方法和对应权限编码的映射 # 注意:Django权限的编码格式是 `{app_label}.{permission_codename}` method_perm_map = { 'GET': 'your_app.view_activity', 'POST': 'your_app.add_activity', 'PUT': 'your_app.change_activity', 'PATCH': 'your_app.change_activity', 'DELETE': 'your_app.delete_activity' } # 获取当前请求需要的权限 required_perm = method_perm_map.get(request.method) if not required_perm: return False # 检查用户是否拥有该权限(包括组权限) return request.user.has_perm(required_perm)
然后修改views.py使用这个自定义权限:
from .permissions import GroupBasedPermission from rest_framework.permissions import IsAuthenticated class MyApi(ModelViewSet): permission_classes = (IsAuthenticated, GroupBasedPermission) queryset = MyModel.objects.all() serializer_class = MyModelSerializer
4. 排查你之前的权限不生效问题
你说已经给组分配了权限、把用户加进组,但还是能访问受限API,大概率是这几个原因:
- 没在视图里添加权限校验类:你之前的代码只有
IsAuthenticated,根本没做权限检查 - 权限编码写错了:Django的权限编码是
{app_label}.{action}_{model_name},比如你的模型是Activity,删除权限的编码是your_app.delete_activity,要确保组里分配的权限和代码里检查的一致 - 缓存问题:Django会缓存权限,修改权限后可能需要重启服务器,或者在Django shell里执行
from django.contrib.auth.models import Permission; Permission.objects.all().update()刷新缓存 - 用户直接拥有权限:如果用户自己被单独分配了权限(不是通过组),会覆盖组权限的限制,要确保用户没有直接的权限分配
5. 测试验证
配置好后,用你的user_xx用户(只拥有add_activity权限)去访问DELETE接口,应该会返回403 Forbidden,这就符合你的预期了。
内容的提问来源于stack exchange,提问作者JPG
相关产品推荐
相关产品推荐

