RBAC权限管理
什么是RBAC ?
RBAC(Role-Based Access Control,基于角色的访问控制),就是用户通过角色与权限进行关联。简单地说,就是权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。
这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便,一般在公司内部使用。
RBAC的表设计
3张表
最开始只有3张表:User表、Group表、Permission表
前2张表都通过外键来和其他表建立联系
5张表
之后分析,User表和Group表是多对多关系,Group表和Permission表也是多对多关系,于是加了2张中间表:User-Group 表和Group-Permission 表,进行了解耦合
6张表
之后,由于某个用户(假设Danny是老板)需要的权限不在Group表中,他拥有的是最高权限(所有权限),于是 就产生了第6张中间表:User-Permission 表
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
class User(models.Model):name = models.CharField(max_length=32)pwd = models.CharField(max_length=32)roles = models.ManyToManyField(to='Role')def __str__(self):return self.nameclass Role(models.Model):title = models.CharField(max_length=32)permissions = models.ManyToManyField(to='Permission')def __str__(self):return self.titleclass Permission(models.Model):name = models.CharField(max_length=32, verbose_name='权限名称')url = models.CharField(max_length=32, verbose_name='权限url')def __str__(self):return self.name
admin.py
from app01 import modelsadmin.site.register(models.User, UserConfig)admin.site.register(models.Role)admin.site.register(models.Permission)
mypermission.py
from django.utils.deprecation import MiddlewareMixinfrom django.shortcuts import HttpResponseimport reclass MyPermission(MiddlewareMixin):def process_request(self, request):# 定义网站白名单white_url_list = ['/login/', '/register/', '/admin/.*']# 1.获取当前用户请求的urltarget_url = request.path# 1.1.先校验是否在白名单中 是则直接放行for url in white_url_list:re_path = '^%s$' % url # 将白名单里面的url变成正则表达式 去校验用户访问的urlres = re.search(re_path, target_url)if res:return# 2.获取当前用户的权限列表permission_list = request.session.get('permission_list')# 3.判断当前请求url在不在用户可以访问的url列表中'''也需要改成正则校验的方式'''# if target_url not in permission_list:# return HttpResponse("没有权限访问")for permission in permission_list:re_path = '^%s$' % permissionres = re.search(re_path, target_url)if res:returnreturn HttpResponse("无法访问,没有权限")
settings.py
# 自定义中间件MIDDLEWARE = ['app01.permissions.mypermission.MyPermission']
views.py
def login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')user_obj = models.User.objects.filter(name=username,pwd=password).first()if user_obj:# 获取当前用户的权限permission_list = models.User.objects.filter(name=username,pwd=password).values('roles__permissions__url').distinct()'''由于用户和权限之前是多对多 所以结果集可能会有重复的元素'''# 存储当前登录用户的权限 便于后续比对permission_list = [i.get("roles__permissions__url") for i in permission_list]# print(permission_list)request.session['permission_list'] = permission_listreturn render(request,'login.html')
Django自带
models.py
from django.contrib.auth.models import AbstractUserfrom django.db import modelsclass UserInfo(AbstractUser):mobile = models.CharField(max_length=11, unique=True)class Meta:verbose_name_plural = '用户信息表'def __str__(self):return self.username
admin
from django.contrib.auth.admin import UserAdmin as DjangoUserAdminfrom django.contrib import adminfrom app_test import models# 自定义User表后,admin界面管理User类class UserAdmin(DjangoUserAdmin):# 添加用户可操作字段add_fieldsets = ((None, {'classes': ('wide',),'fields': ('username', 'password', 'is_staff', 'mobile', 'groups', 'user_permissions'),}),)# 展示用户呈现的字段list_display = ('username', 'mobile', 'is_staff', 'is_active', 'is_superuser')admin.site.register(models.UserInfo, UserAdmin)
settings.py
AUTH_USER_MODEL = 'app_test.UserInfo'



