RBAC权限管理

什么是RBAC ?

RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,就是权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。

这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便,一般在公司内部使用。

RBAC的表设计

3张表

最开始只有3张表:User表Group表Permission表

前2张表都通过外键来和其他表建立联系

Django之RBAC权限管理 - 图1

5张表

之后分析,User表Group表多对多关系,Group表Permission表也是多对多关系,于是加了2张中间表User-Group 表Group-Permission 表,进行了解耦合

Django之RBAC权限管理 - 图2

6张表

之后,由于某个用户(假设Danny是老板)需要的权限不在Group表中,他拥有的是最高权限(所有权限),于是 就产生了第6张中间表:User-Permission 表

Django之RBAC权限管理 - 图3

Django内置的RBAC的6张表

Django中所使用的是六表权限,(基本上五表权限就够了),它包含了用户与组的关系,用户与权限的关系(很重要),以及组与权限的关系。

表名 释义
auth_user 用户表
auth_group 角色表(组表)
auth_permission 权限表
auth_user_groups 用户-角色 中间表
auth_group_permisssions 角色-权限 中间表
auth_user_user_permissions 用户-权限 中间表

在Django中,分为3种角色:

  • 普通用户(无法登入后台)
  • 工作人员(可以登入后台)—— is_staff
  • 超级管理员(可以登入后台,拥有所有权限)—— is_superuser

使用

自定义

models.py

  1. class User(models.Model):
  2. name = models.CharField(max_length=32)
  3. pwd = models.CharField(max_length=32)
  4. roles = models.ManyToManyField(to='Role')
  5. def __str__(self):
  6. return self.name
  7. class Role(models.Model):
  8. title = models.CharField(max_length=32)
  9. permissions = models.ManyToManyField(to='Permission')
  10. def __str__(self):
  11. return self.title
  12. class Permission(models.Model):
  13. name = models.CharField(max_length=32, verbose_name='权限名称')
  14. url = models.CharField(max_length=32, verbose_name='权限url')
  15. def __str__(self):
  16. return self.name

admin.py

  1. from app01 import models
  2. admin.site.register(models.User, UserConfig)
  3. admin.site.register(models.Role)
  4. admin.site.register(models.Permission)

mypermission.py

  1. from django.utils.deprecation import MiddlewareMixin
  2. from django.shortcuts import HttpResponse
  3. import re
  4. class MyPermission(MiddlewareMixin):
  5. def process_request(self, request):
  6. # 定义网站白名单
  7. white_url_list = ['/login/', '/register/', '/admin/.*']
  8. # 1.获取当前用户请求的url
  9. target_url = request.path
  10. # 1.1.先校验是否在白名单中 是则直接放行
  11. for url in white_url_list:
  12. re_path = '^%s$' % url # 将白名单里面的url变成正则表达式 去校验用户访问的url
  13. res = re.search(re_path, target_url)
  14. if res:
  15. return
  16. # 2.获取当前用户的权限列表
  17. permission_list = request.session.get('permission_list')
  18. # 3.判断当前请求url在不在用户可以访问的url列表中
  19. '''也需要改成正则校验的方式'''
  20. # if target_url not in permission_list:
  21. # return HttpResponse("没有权限访问")
  22. for permission in permission_list:
  23. re_path = '^%s$' % permission
  24. res = re.search(re_path, target_url)
  25. if res:
  26. return
  27. return HttpResponse("无法访问,没有权限")

settings.py

  1. # 自定义中间件
  2. MIDDLEWARE = [
  3. 'app01.permissions.mypermission.MyPermission'
  4. ]

views.py

  1. def login(request):
  2. if request.method == 'POST':
  3. username = request.POST.get('username')
  4. password = request.POST.get('password')
  5. user_obj = models.User.objects.filter(name=username,pwd=password).first()
  6. if user_obj:
  7. # 获取当前用户的权限
  8. permission_list = models.User.objects.filter(name=username,pwd=password).values('roles__permissions__url').distinct()
  9. '''由于用户和权限之前是多对多 所以结果集可能会有重复的元素'''
  10. # 存储当前登录用户的权限 便于后续比对
  11. permission_list = [i.get("roles__permissions__url") for i in permission_list]
  12. # print(permission_list)
  13. request.session['permission_list'] = permission_list
  14. return render(request,'login.html')

Django自带

models.py

  1. from django.contrib.auth.models import AbstractUser
  2. from django.db import models
  3. class UserInfo(AbstractUser):
  4. mobile = models.CharField(max_length=11, unique=True)
  5. class Meta:
  6. verbose_name_plural = '用户信息表'
  7. def __str__(self):
  8. return self.username

admin

  1. from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
  2. from django.contrib import admin
  3. from app_test import models
  4. # 自定义User表后,admin界面管理User类
  5. class UserAdmin(DjangoUserAdmin):
  6. # 添加用户可操作字段
  7. add_fieldsets = (
  8. (None, {
  9. 'classes': ('wide',),
  10. 'fields': ('username', 'password', 'is_staff', 'mobile', 'groups', 'user_permissions'),
  11. }),
  12. )
  13. # 展示用户呈现的字段
  14. list_display = ('username', 'mobile', 'is_staff', 'is_active', 'is_superuser')
  15. admin.site.register(models.UserInfo, UserAdmin)

settings.py

  1. AUTH_USER_MODEL = 'app_test.UserInfo'