一:学习总结

  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
models

 


(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('添加订单页面') 
app01_view

 

(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中
rbac_init_permission

 

(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("无权访问")
rbac_中间件