71. drf之访问控制模型

1. ACL

访问控制列表Access Control List

给资源绑定权限清单:记录哪些主体可以对该资源做什么操作。多用于互联网软件。

  视角:站在资源侧
  格式示例:资源 A → [用户张三:读,用户李四:读写]

特点:

  简单直观,适合资源数量少的场景(如服务器文件权限)
  扩展性差:用户、资源变多后,配置变多;无法批量管理。
  例:新增 100 个用户,要逐个在每个资源上添加权限。

典型场景:

  Linux 文件权限、网络防火墙规则。

image

用户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。

权限三表

image

权限六表

 

image

用户和角色是多对多  使用中间表

角色和权限是多对多  使用中间表

 

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迁移至数据库中

创建一个超级用户

image

image

管理页面汉化settings.py中

LANGUAGE_CODE = 'zh-hans'

TIME_ZONE = 'Asia/Shanghai'

USE_I18N = True

USE_TZ = False

登陆管理页面

image

image

在admin.py注册之后前端可以看到表

from django.contrib import admin

# Register your models here.

from .models import User, Book
admin.site.register(User)
admin.site.register(Book)

image

修改字段在页面展示的名称

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'

image

图书表增加记录

image

image

image

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

image

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

image

注册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表,默认都是超级用户

image

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

image

 

增加图书查看和新增组

image

 

posted @ 2026-10-05 01:45  pythondjango  阅读(4)  评论(0)    收藏  举报