Django REST 框架详解 07 | 三大认证与权限六表

2021-01-12 10:01:07 浏览数 (1)

文章目录

    • 一、三大认证
        • 1. 认证组件:校验用户
        • 2. 权限组件:校验用户权限
        • 3. 频率组件:限制视图接口被访问次数
        • 4. 分析源码
    • 二、权限六表
        • 1. RBAC 认证
        • 2. 权限三表
        • 3. 权限五表
        • 4. 权限六表
    • 三、六表间访问
        • 1. 分析源码
        • 2. 六表间访问方法
        • 3. 代码实现
        • 4. 脚本化启动查看表

一、三大认证

1. 认证组件:校验用户
  • 游客:无认证信息,校验通过,直接进入下一步权限认证校验
  • 合法用户:带正确认证信息,校验通过,将用户存储在 request.user 中,再下一步权限认证校验
  • 非法用户:带错误认证信息,校验失败,抛出异常,返回 403 权限异常结果

详细:Django REST 框架详解 08 | 认证组件

2. 权限组件:校验用户权限
  • 必须登录
  • 所有用户
  • 登录读写,游客只读
  • 自定义用户角色

认证通过:可以进入下一步校验(频率认证)

认证失败:抛出异常,返回 403

详细:Django REST 框架详解 09 | 权限组件

3. 频率组件:限制视图接口被访问次数
  • 限制的条件:IP,userid,唯一键(如手机号)
  • 频率周期时间:s,m,h,d
  • 频率的次数:3/h

没有达到限次:正常访问

达到限次:限制时间内不能访问,返回500,限制时间达到后,可以重新访问

详细:Django REST 框架详解 10 | 频率认证组件

4. 分析源码
代码语言:javascript复制
class APIView(View):
    # ...
    def initial(self, request, *args, **kwargs):
        """
        Runs anything that needs to occur prior to calling the method handler.
        """
        self.format_kwarg = self.get_format_suffix(**kwargs)

        # Perform content negotiation and store the accepted info on the request
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg

        # Determine the API version, if versioning is in use.
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme

        # Ensure that the incoming request is permitted
        # 认证组件:校验用户
        self.perform_authentication(request)
        # 权限组件:校验用户权限
        self.check_permissions(request)
        # 频率组件:限制视图接口被访问次数
        self.check_throttles(request)

二、权限六表

基于用户角色权限访问的控制 (RBAC,Role Based Access Control):Django 框架使用

基于 auth 认证:ThinkPHP 使用

1. RBAC 认证

RBAC 认证规则通常会分为 三表规则,五表规则,Django 采用六表规则

2. 权限三表

用户表,角色表,权限表

User

id

name

g_id

1

小明

1

2

小白

2

3

小红

2,3

Group

id

name

p_id

1

校长

1

2

讲师

1,2,3

3

助教

1,3

Permission

id

name

1

管理

2

授课

3

答疑

4

财务

3. 权限五表

会发现权限三表中,User 表与 Group 表多对多关系, Group 表与 Permission 表是多对多关系。所以,需要新建这两张的关系表,这就是权限五表。

用户表,角色表,权限表,用户角色关系表,角色权限关系表

U-G关系表

id

u_id

g_id

1

1

1

2

2

2

3

3

2

4

3

3

G-P关系表

id

g_id

p_id

1

1

1

2

2

1

3

2

2

4

2

3

5

3

1

6

3

3

User

id

name

1

小明

2

小白

3

小红

Group

id

name

1

校长

2

讲师

3

助教

Permission

id

name

1

管理

2

授课

3

答疑

4. 权限六表

有的用户可能会执行角色分组以外的权限,所以除了五表外,多了用户表与权限表的关系表。

用户表,角色表,权限表,用户角色关系表,角色权限关系表,用户权限关系表。

U-P关系表

id

u_id

p_id

1

1

4

2

2

4

3

3

4

三、六表间访问

1. 分析源码

auth/models.py

代码语言:javascript复制
class PermissionsMixin(models.Model):
    """
    Add the fields and methods necessary to support the Group and Permission
    models using the ModelBackend.
    """
    is_superuser = models.BooleanField(
        _('superuser status'),
        default=False,
        help_text=_(
            'Designates that this user has all permissions without '
            'explicitly assigning them.'
        ),
    )
    # 用户-角色关系表
    groups = models.ManyToManyField(
        Group,
        verbose_name=_('groups'),
        blank=True,
        help_text=_(
            'The groups this user belongs to. A user will get all permissions '
            'granted to each of their groups.'
        ),
        related_name="user_set",
        related_query_name="user",
    )
    # 用户-权限关系表
    user_permissions = models.ManyToManyField(
        Permission,
        verbose_name=_('user permissions'),
        blank=True,
        help_text=_('Specific permissions for this user.'),
        related_name="user_set",
        related_query_name="user",
    )

auth/models.py

代码语言:javascript复制
class Group(models.Model):
    # 角色-权限关系表
    name = models.CharField(_('name'), max_length=150, unique=True)
    permissions = models.ManyToManyField(
        Permission,
        verbose_name=_('permissions'),
        blank=True,
    )
2. 六表间访问方法

用户表:访问角色 groups, 访问权限 user_permissions 角色表:访问用户 user_set, 访问权限 permissions 权限表:访问用户 user_set, 访问角色 group_set

3. 代码实现

自定义用户表 models.py

代码语言:javascript复制
class User(AbstractUser):
    mobile = models.CharField(max_length=11, unique=True)

    class Meta:
        db_table = 'api_user',
        verbose_name = '用户表',
        verbose_name_plural = verbose_name

    def __str__(self):
        return self.username

数据库迁移

代码语言:javascript复制
python manage.py makemigrations
python manage.py migrrate

迁移报错解决 如果自定义 User 表后,在另一个项目中采用原生 User 表,完成数据库迁移时,可能会失败 解决:

  1. 卸载 Django 重新装
  2. 清空数据库迁移记录文件 django.contrib.admin.migraions 清空除了 init.py 以外的文件 django.contrib.auth.migraions 清空除了 init.py 以外的文件

创建成功后数据库表如下:

4. 脚本化启动查看表
代码语言:javascript复制
# django 脚本化启动
import os, django

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'drf_proj02.settings')
django.setup()

from api import models
user = models.User.objects.first()
# 用户
print(user.username)
# 用户-角色
print(user.groups.first())
# 用户-权限
print(user.user_permissions.first().name)

print("-"*20)
from django.contrib.auth.models import Group
group = Group.objects.first()
# 权限名
print(group.name)
# 权限-用户
print(group.user_set.first().username)
# 权限-分组
print(group.permissions.first().name)

print("-"*20)
from django.contrib.auth.models import Permission
p_1 = Permission.objects.filter(pk=1).first()
# 权限-用户
print(p_1.user_set.first().username)
p_2 = Permission.objects.filter(pk=2).first()
# 权限-角色
print(p_2.group_set.first().name)

0 人点赞