基于React Native+DRF的LMS仅管理员创建用户的RBAC实现咨询
Django DRF 三角色RBAC实现方案
1. 自定义User模型与UserManager
首先替换Django默认的User模型,新增角色标识字段和你需要的业务额外属性:
from django.contrib.auth.models import BaseUserManager, AbstractUser from django.db import models # 自定义用户管理器 class CustomUserManager(BaseUserManager): def create_user(self, email, password=None, role='student', **extra_fields): if not email: raise ValueError('用户必须提供邮箱地址') email = self.normalize_email(email) # 强制锁死普通用户的管理员权限,避免非法提权 extra_fields.setdefault('is_staff', False) extra_fields.setdefault('is_superuser', False) # 根据传入角色自动设置身份字段 extra_fields['is_instructor'] = (role == 'instructor') extra_fields['is_student'] = (role == 'student') user = self.model(email=email, **extra_fields) user.set_password(password) user.save(using=self._db) return user def create_superuser(self, email, password=None, **extra_fields): extra_fields.setdefault('is_staff', True) extra_fields.setdefault('is_superuser', True) extra_fields.setdefault('is_instructor', False) extra_fields.setdefault('is_student', False) if extra_fields.get('is_staff') is not True: raise ValueError('超级用户必须设置is_staff=True') if extra_fields.get('is_superuser') is not True: raise ValueError('超级用户必须设置is_superuser=True') return self.create_user(email, password, **extra_fields) # 自定义用户模型 class CustomUser(AbstractUser): # 替换默认username字段为邮箱作为唯一标识 username = None email = models.EmailField('邮箱地址', unique=True) # 角色标识字段 is_instructor = models.BooleanField('是否为讲师', default=False) is_student = models.BooleanField('是否为学生', default=False) # 业务额外属性示例,可按需扩展 employee_id = models.CharField('工号/学号', max_length=20, blank=True) department = models.CharField('所属院系', max_length=100, blank=True) USERNAME_FIELD = 'email' REQUIRED_FIELDS = [] objects = CustomUserManager() def __str__(self): return self.email
注意:如果你已经执行过Django初始迁移,替换默认User模型会引发冲突,建议项目初始化阶段先配置自定义User模型,再执行第一次migrate。配置完成后需要在settings.py中添加AUTH_USER_MODEL = '你的应用名称.CustomUser'
2. 自定义DRF权限类
新建permissions.py文件,实现不同角色的访问拦截逻辑:
from rest_framework.permissions import BasePermission # 仅管理员可访问权限 class IsAdminOnly(BasePermission): def has_permission(self, request, view): return request.user and request.user.is_authenticated and request.user.is_staff # 仅讲师可访问权限 class IsInstructorOnly(BasePermission): def has_permission(self, request, view): return request.user and request.user.is_authenticated and request.user.is_instructor # 仅学生可访问权限 class IsStudentOnly(BasePermission): def has_permission(self, request, view): return request.user and request.user.is_authenticated and request.user.is_student
3. 实现管理员创建用户的接口
序列化器代码
from rest_framework import serializers from .models import CustomUser class UserCreateSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True, min_length=8) # 限制仅可创建学生/讲师两类账号 role = serializers.ChoiceField(choices=[('student', '学生'), ('instructor', '讲师')], write_only=True) class Meta: model = CustomUser fields = ['email', 'password', 'role', 'first_name', 'last_name', 'employee_id', 'department'] def create(self, validated_data): role = validated_data.pop('role') return CustomUser.objects.create_user(role=role, **validated_data)
视图代码
from rest_framework import generics from .models import CustomUser from .serializers import UserCreateSerializer from .permissions import IsAdminOnly class UserCreateView(generics.CreateAPIView): queryset = CustomUser.objects.all() serializer_class = UserCreateSerializer # 绑定管理员权限,仅管理员可调用该接口创建用户 permission_classes = [IsAdminOnly]
将视图注册到urls.py后即可使用,管理员登录后调用该接口就能创建指定身份的账号。
4. 前端适配方案
React Native端登录后,后端返回用户的is_staff/is_instructor/is_student字段,前端根据字段值渲染对应角色的页面菜单、拦截未授权的功能跳转即可。如果使用JWT鉴权,可以将角色字段写入JWT payload,前端解码后直接读取身份信息。
补充注意点
- 不要信任前端传入的
is_staff、is_superuser字段,上述UserManager代码已经强制拦截了这两个字段的普通写入,仅创建超级用户时可修改,避免被非法提权 - 如果后续需要更细粒度的对象级权限(比如讲师仅可修改自己发布的课程),可以结合
django-guardian实现,当前三角色场景使用自定义字段+权限类完全满足需求 - 所有业务接口都需要绑定对应权限类,避免未登录用户或非授权角色访问敏感数据
内容的提问来源于stack exchange,提问作者Ravi Trivedi
相关产品推荐
相关产品推荐

