一:学习总结
Dganjo的rbac(角色权限控制)
二:步骤
(1)在项目中创建rbac的app
(2)rbac创建3类5表的数据库
1 from django.db import models 2 3 # Create your models here. 4 """ 5 用户的权限设置在url中,表里可以存放所有的url 6 根据角色来分配权限 7 """ 8 9 class Permission(models.Model): 10 """ 11 权限表 12 """ 13 title=models.CharField(verbose_name='标题',max_length=32) 14 url=models.CharField(verbose_name='含有正则的url',max_length=32) 15 16 is_menu=models.BooleanField(verbose_name='是否做菜单') # 添加一个布尔类型,来判断这个权限能否做菜单,列表可以,添加、删除、编辑不可以 17 18 class Meta: # 作用是在admin录入数据时,表名显示中文 19 verbose_name_plural="权限表" 20 21 def __str__(self): # 在admin中数据显示某个字段 22 return self.title 23 24 25 26 class User(models.Model): 27 """ 28 用户表 29 """ 30 username=models.CharField(verbose_name='用户名',max_length=32) 31 password=models.CharField(verbose_name='密码',max_length=32) 32 email=models.CharField(verbose_name='邮箱',max_length=32) 33 34 roles=models.ManyToManyField(verbose_name='具有的角色',to="Role") 35 36 class Meta: 37 verbose_name_plural="用户表" 38 39 def __str__(self): 40 return self.username 41 42 43 class Role(models.Model): 44 """ 45 角色表 46 """ 47 title=models.CharField(verbose_name='角色名称',max_length=32) 48 permission=models.ManyToManyField(to="Permission") 49 50 class Meta: 51 verbose_name_plural="角色表" 52 53 def __str__(self): 54 return self.title
(3)使用命令生成数据库
python manage.py makemigrations
python manage.py migrate
(4)创建Django本身的超级用户
python manage.py createsuperuser
(5)进入admin页面之后添加记录,分配权限
(6)在app01中创建登录界面
1 ==注意:对于session的验证,可以写在rbac中,用init_permission(user,request)封装== 2 3 app01.views: 4 5 from django.shortcuts import render,redirect,HttpResponse 6 from rbac import models 7 from rbac.service.init_permission import init_permission 8 9 def login(request): 10 if request.method=="GET": 11 return render(request,"login.html") 12 else: 13 user=request.POST.get("user") 14 pwd=request.POST.get("pwd") 15 user=models.User.objects.filter(username=user,password=pwd).first() 16 if not user: 17 return render(request,"login.html") 18 init_permission(user,request) # 在init_permission()函数中通过用户获取permission_url,并写入到session注册中 19 20 return redirect("/index/") 21 22 23 def userinfo(request): 24 return HttpResponse('用户列表页面') 25 26 27 def userinfo_add(request): 28 return HttpResponse('添加用户页面') 29 30 def order(request): 31 return HttpResponse('订单列表页面') 32 33 def order_add(request): 34 return HttpResponse('添加订单页面')
(7)写rbac的init_permission(user,request)函数
1 ==注意:用户通过角色查询到的权限要去重。跨表查询取得权限之后,赋值给列表,再加到session中== 2 3 def init_permission(user,request): 4 """ 5 获得用户登录的url权限 6 把权限加到session中 7 :param user: 8 :param request: 9 :return: 10 """ 11 permission_list=user.roles.values("permission__title","permission__url","permission__is_menu").distinct() # 要对权限进行去重,因为权限跟角色多对多,会重复 12 13 url_list=[] 14 for item in permission_list: 15 url_list.append(item["permission__url"]) 16 17 request.session["permission_url_list"]=url_list # 将查询到的权限写入session中
(8)rbac中写中间件,实现对白名单以及session中权限的验证
注意:
(1)先继承MiddlewareMixin类,中间件定义process_request(self,request)方法
(2)获取当前的url
current_url=request.path_info
(3)检验是否在白名单中
for url in settings.VALID_URL:
if re.match(url,current_url):
return None
如果在就返回None,直接执行后续的中间件,本函数不继续执行
(4)在setting中创建白名单并注册中间件
'rbac.middlewares.rbac.RbacMiddleware',
VALID_URL=[
"^/login/$",
"/admin.*",
]
(5)如果不在白名单,就与session比较,通过re匹配,并且要加开始终止符,匹配成功即有权限
permision_list=request.session.get("permission_url_list")
if not permision_list:
return redirect("/login/")
flag=False
for db_url in permision_list:
regax="^{0}$".format(db_url) # 加开始与终止符
if re.match(regax,current_url):
flag=True
break
if not flag:
return HttpResponse("无权访问")
1 import re 2 3 from django.shortcuts import redirect,render,HttpResponse 4 from django.conf import settings 5 6 """ 7 设置中间件 8 设置白名单,限制谁可以不用验证session,可以直接过去 9 并且匹配URL权限 10 """ 11 12 class MiddlewareMixin(object): 13 def __init__(self, get_response=None): 14 self.get_response = get_response 15 super(MiddlewareMixin, self).__init__() 16 17 def __call__(self, request): 18 response = None 19 if hasattr(self, 'process_request'): 20 response = self.process_request(request) 21 if not response: 22 response = self.get_response(request) 23 if hasattr(self, 'process_response'): 24 response = self.process_response(request, response) 25 return response 26 27 class RbacMiddleware(MiddlewareMixin): 28 def process_request(self,request): 29 current_url=request.path_info # 获取当前的url 30 31 for url in settings.VALID_URL: #判断当前url是否在白名单中 32 if re.match(url,current_url): 33 return None 34 35 permision_list=request.session.get("permission_url_list") # 获取session中的url权限 36 37 if not permision_list: 38 return redirect("/login/") 39 40 flag=False 41 for db_url in permision_list: 42 regax="^{0}$".format(db_url) # 对session中的url加起始终止符,与当前url匹配,获取权限 43 if re.match(regax,current_url): 44 flag=True 45 break 46 47 if not flag: 48 return HttpResponse("无权访问")
浙公网安备 33010602011771号