You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 15:57:03