71. drf之访问控制模型
1. ACL
访问控制列表Access Control List
给资源绑定权限清单:记录哪些主体可以对该资源做什么操作。多用于互联网软件。
视角:站在资源侧
格式示例:资源 A → [用户张三:读,用户李四:读写]
特点:
简单直观,适合资源数量少的场景(如服务器文件权限)
扩展性差:用户、资源变多后,配置变多;无法批量管理。
例:新增 100 个用户,要逐个在每个资源上添加权限。
Linux 文件权限、网络防火墙规则。

用户id为1的权限列表 1: [2, 3]
用户id为2的权限列表 2: [1, 2]
2. RBAC
基于角色的访问控制 Role-Based Access Control
用户 ↔ 角色 ↔ 权限
不给用户直接分配权限,而是定义角色,把权限绑定到角色;用户关联角色从而获得权限。多用于公司内部项目。
视角:站在用户身份侧
链路:用户 → 角色 → 权限 (资源 + 操作)
细分版本
RBAC0:基础版,用户 - 角色多对多,角色 - 权限多对多
RBAC1:增加角色继承(管理员继承普通用户权限)
RBAC2:增加约束,如互斥角色(不能同时是管理员和访客)
RBAC3:RBAC1 + RBAC2
特点
业务最常用,权限批量管理;用户岗位变动只需要更换角色,不用改一堆权限
只依靠角色身份,无法根据动态属性做细粒度判断。
例:角色是 “销售”,但只能看自己的客户数据,单纯 RBAC 很难天然实现。
典型场景
后台管理系统、OA、企业 ERP。
权限三表

权限六表

用户和角色是多对多 使用中间表
角色和权限是多对多 使用中间表
3. ABAC
基于属性的访问控制Attribute-Based Access Control根据属性动态计算权限。属性分为三类:
主体属性:用户部门、职位、ID
资源属性:创建人、所属部门、密级
环境属性:访问时间、IP 地址
规则示例:
if (用户.部门 == 数据.所属部门) and (当前时间在工作日9-18点) then 允许读
特点
支持极细粒度、动态权限;不需要提前定义大量角色,适合数据权限
规则复杂,调试困难;规则变多后可读性、性能下降
典型场景
云资源权限、数据脱敏、隐私系统、多租户数据权限。
4. 访问控制模型总结
| 模型 | 核心要素 | 优点 | 缺点 | 适合场景 |
|---|---|---|---|---|
| ACL | 资源绑定主体权限 | 简单 | 难扩展,资源多配置爆炸 | 文件、防火墙 |
| RBAC | 用户 - 角色 - 权限 | 易维护,成熟 | 只靠角色,缺少动态条件 | 后台功能权限 |
| ABAC | 主体 / 资源 / 环境属性 | 动态细粒度 | 规则复杂难维护 | 数据权限、云访问 |
ACL:这个文件允许谁访问
RBAC:这个角色能干哪些功能
ABAC:满足这些条件才可以访问这条数据
5. Django的权限控制
5.1 Django的RBAC
[1] 概念
django.contrib.auth模块提供了RBAC相关的数据模型和方法,用于基于角色的访问控制的实现。
auth_user:
用户表。
用户的登录凭证、个人信息等。
auth_group:
角色(组)表。
每个角色代表一组具有相同权限的用户集合。
作用:定义角色,例如"管理员"、"普通用户"。
auth_permission:
权限表。
作用:定义权限,如"添加用户"、"编辑数据"等。
auth_user_groups:
用户与组之间的多对多关系表。
作用:分配角色,将用户分配给对应的角色(组)。
auth_group_permissions:
组与权限之间的多对多关系表。
作用:授予权限,将权限授予不同的角色(组)。
auth_user_user_permissions:
用户与权限之间的多对多关系表。
作用:直接赋权,给用户直接添加权限。
基于Django的auth+admin开发:
Django提供了内置的用户认证(auth)和管理后台(admin)功能,可通过对用户、组和权限进行管理来实现RBAC。
[2] 代码与RBAC演示
app01的models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
# 扩写:自定义auth_user表
class UserInfo(AbstractUser):
# 只需要写自定义字段,默认字段在基类中
mobile = models.CharField(max_length=11)
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32) # 密码没有加密
age = models.IntegerField()
hobby = models.IntegerField(choices=((1, 'sing'), (2, 'rap')), default=2)
class Book(models.Model):
name = models.CharField(max_length=32)
settings.py中指定auth_user表
AUTH_USER_MODEL = 'app01.UserInfo'
makemigrations-migrate迁移至数据库中
创建一个超级用户


管理页面汉化settings.py中
LANGUAGE_CODE = 'zh-hans'
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_TZ = False
登陆管理页面


在admin.py注册之后前端可以看到表
from django.contrib import admin
# Register your models here.
from .models import User, Book
admin.site.register(User)
admin.site.register(Book)

修改字段在页面展示的名称
class Book(models.Model):
name = models.CharField(max_length=32)
class Meta:
verbose_name = '图书表001' # 模型单数名称,Admin 后台显示单个对象时用
verbose_name_plural = verbose_name # 模型复数名称,Admin后台在模型列表页的标题
修改应用在页面展示的名称,app01的apps.py
from django.apps import AppConfig
class App01Config(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'app01'
verbose_name = '应用1'

图书表增加记录



将前端展示的对象名称按实际展示

class Book(models.Model):
name = models.CharField(max_length=32)
class Meta:
verbose_name = '图书表001' # 模型单数名称,Admin 后台显示单个对象时用
verbose_name_plural = verbose_name # 模型复数名称,Admin后台在模型列表页的标题
def __str__(self):
return self.name

注册UserInfo表
from django.contrib import admin
# Register your models here.
from .models import User, Book, UserInfo
admin.site.register(User)
admin.site.register(Book)
admin.site.register(UserInfo)
“用户”即auth_user表,默认都是超级用户

超级用户默认属于所有组、拥有所有权限

增加图书查看和新增组


浙公网安备 33010602011771号