rbac(基於角色權限控制)-------權限管理



權限管理
  創建一個rbac和app的應用,這個rbac主要是用來存放權限的,全稱叫做基於角色權限控制
  一、先看配置文件合適不,給創建的rbac在配置文件里面設置一下
    找到INSTALLED_APPS=【'rbac'】
  二、設計表結構
    models中創建類:五個類,七張表
    角色表:
    用戶表:
    權限表:

     組表:

     菜單表:

    角色表和權限表是多對多的關系(一個角色可以有多個權限,一個權限可以對應多個角色)
    用戶表和角色表是多對多的關系(一個用戶可以有多個角色,一個角色有多個用戶)

    所以有會多生成兩張關系表

    一個菜單下面有多個組

    一個組下面有多個菜單

    一個菜單下面有多個權限

復制代碼
from django.db import models

# Create your models here.
class Role(models.Model):
'''
角色表
'''
title
= models.CharField(max_length=32,verbose_name="角色名")
permissions
= models.ManyToManyField(to="Permission",verbose_name="具有的所有權限", blank=True) # 建立用戶表和角色表的多對多關系

<span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title

</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
    verbose_name_plural </span>= <span style="color: #800000;">"</span><span style="color: #800000;">角色表</span><span style="color: #800000;">"</span>

class Group(models.Model):
caption
= models.CharField(max_length=32,verbose_name="組名稱")
menu
= models.ForeignKey(to="Menu",verbose_name="所屬菜單",default=1,related_name="menu")
class Menu(models.Model):
title
= models.CharField(max_length=32)

class Permission(models.Model):
'''
權限表
'''
title
= models.CharField(max_length=32,verbose_name="標題")
url
= models.CharField(max_length=64,verbose_name="帶正則的URL")
# is_mune = models.BooleanField(verbose_name="是否是菜單",default=0)
menu_gp = models.ForeignKey(verbose_name="組內菜單",to="Permission",blank=True,null=True) #自關聯
#主頁就可以設置為菜單,當點擊菜單的時候才可以做具體的操作
codes = models.CharField(max_length=32,verbose_name="代碼",default=1)
group
= models.ForeignKey(to="Group",verbose_name="所屬組",null=True) #新添加的字段記得設置默認值

<span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.title

</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
    </span><span style="color: #800000;">'''</span><span style="color: #800000;">中文顯示</span><span style="color: #800000;">'''</span><span style="color: #000000;">
    verbose_name_plural </span>= <span style="color: #800000;">"</span><span style="color: #800000;">權限表</span><span style="color: #800000;">"</span>

class UserInfo(models.Model):
'''
用戶表
'''
username
= models.CharField(max_length=32,verbose_name="用戶名")
password
= models.CharField(max_length=64,verbose_name="密碼")
email
= models.CharField(max_length=32,verbose_name="郵箱")
roles
= models.ManyToManyField(to="Role",verbose_name="具有的所有角色",blank=True) #建立用戶和角色的多對多關系

<span style="color: #0000ff;">def</span> <span style="color: #800080;">__str__</span><span style="color: #000000;">(self):
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> self.username

</span><span style="color: #0000ff;">class</span><span style="color: #000000;"> Meta:
    verbose_name_plural </span>= <span style="color: #800000;">"</span><span style="color: #800000;">用戶表</span><span style="color: #800000;">"</span></pre>
復制代碼

 


  三、通過django admin錄入權限數據
    - 先創建一個超級用戶
    - 用戶名 root
    - 密碼 zhy123456
    - 在admin.py 中
      from rbac import models
      admin.site.register(models.Permission)
      admin.site.register(models.Role)
      admin.site.register(models.UserInfo)
      這樣的話上去的是英文的,如果你想讓中文顯示就在類中加一個類
      class Meta:
      verbose_name_plural = "權限表"
      - 當你給關聯字段錄入數據的時候會有錯誤提示,那么在類中你的那個關聯字段在加一個屬性blank = True 可以為空
      permissions = models.ManyToManyField(to="Permission",verbose_name="具有的所有權限", blank=True)

  四、編寫登錄
    用戶登錄后:
      獲取當前用戶具有的所有角色
      獲取當前用戶具有的所有權限(並且去重)

復制代碼
      #獲取當前的用戶對象
      user = models.UserInfo.objects.filter(username=name,password=password).first()
      #獲取當前用戶的所有角色user.roles.all()
      #獲取當前用戶的所有權限
      permission_list = user.roles.all().values("permissions__title","permissions__url","permissions__is_mune").distinct()
      print(permission_list)
復制代碼

      登錄成功之后初始化---把所有的url都拿出來並且保存到session里
        1、可以建一個server的包,在里面建一個初始化的init_perssion.py文件
        2、定義函數

 

復制代碼
#!usr/bin/env python
# -*- coding:utf-8 -*-
from rbac import models
from day7權限管理 import settings
def init_permission(user,request):
    #獲取當前的用戶對象
    '''
    獲取所有權限中的url並放在session中
    :param user:
    :param request:
    :return:
    '''
<span style="color: #008000;">#</span><span style="color: #008000;">user.roles.all()獲取當前用戶的所有角色</span>
<span style="color: #008000;">#</span><span style="color: #008000;">獲取當前用戶的所有權限</span>
permission_list =<span style="color: #000000;"> user.roles.all().values(
    </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__id</span><span style="color: #800000;">"</span><span style="color: #000000;">,
    </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__title</span><span style="color: #800000;">"</span>,  <span style="color: #008000;">#</span><span style="color: #008000;">用戶列表</span>
    <span style="color: #800000;">"</span><span style="color: #800000;">permissions__url</span><span style="color: #800000;">"</span>,    <span style="color: #008000;">#</span><span style="color: #008000;">url</span>
    <span style="color: #800000;">"</span><span style="color: #800000;">permissions__menu_gp</span><span style="color: #800000;">"</span>,  <span style="color: #008000;">#</span><span style="color: #008000;">組內菜單id,如果為null表示是菜單</span>
    <span style="color: #800000;">"</span><span style="color: #800000;">permissions__codes</span><span style="color: #800000;">"</span><span style="color: #000000;">,
    </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__group_id</span><span style="color: #800000;">"</span><span style="color: #000000;">,
    </span><span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__title</span><span style="color: #800000;">"</span>,  <span style="color: #008000;">#</span><span style="color: #008000;">菜單名稱</span>
    <span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__id</span><span style="color: #800000;">"</span>  <span style="color: #008000;">#</span><span style="color: #008000;">菜單id</span>

).distinct()

</span><span style="color: #0000ff;">print</span>(<span style="color: #800000;">"</span><span style="color: #800000;">-----------------</span><span style="color: #800000;">"</span><span style="color: #000000;">,permission_list)
</span><span style="color: #008000;">#</span><span style="color: #008000;">菜單相關</span>
sub_permisson_list =<span style="color: #000000;"> []
</span><span style="color: #0000ff;">for</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> permission_list:
    tpl </span>=<span style="color: #000000;"> {
        </span><span style="color: #800000;">"</span><span style="color: #800000;">id</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__id</span><span style="color: #800000;">"</span><span style="color: #000000;">],
        </span><span style="color: #800000;">"</span><span style="color: #800000;">title</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__title</span><span style="color: #800000;">"</span><span style="color: #000000;">],
        </span><span style="color: #800000;">"</span><span style="color: #800000;">url</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__url</span><span style="color: #800000;">"</span><span style="color: #000000;">],
        </span><span style="color: #800000;">"</span><span style="color: #800000;">menu_group_id</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group_id</span><span style="color: #800000;">"</span><span style="color: #000000;">],
        </span><span style="color: #800000;">"</span><span style="color: #800000;">menu_id</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__id</span><span style="color: #800000;">"</span><span style="color: #000000;">],
        </span><span style="color: #800000;">"</span><span style="color: #800000;">menu_title</span><span style="color: #800000;">"</span>:item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group__menu__title</span><span style="color: #800000;">"</span><span style="color: #000000;">]
    }
    sub_permisson_list.append(tpl)
request.session[settings.PERMISSION_MENU_KEY] </span>=<span style="color: #000000;"> sub_permisson_list
</span><span style="color: #008000;">#</span><span style="color: #008000;"> 1、去掉不是菜單的url</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> 菜單操作</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> menu_list = []</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> for item in permission_list:</span>
<span style="color: #008000;">#</span><span style="color: #008000;">     if not item["permissions__is_mune"]:  # 如果不是菜單就繼續</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         continue</span>
<span style="color: #008000;">#</span><span style="color: #008000;">     else:  # 否則是菜單的話就把菜單添加到列表里面</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         tpl = {</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "menu_id": item["permissions__group__menu__id"],</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "menu_title": item["permissions__group__menu__title"],</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "title": item["permissions__title"],</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "url": item["permissions__url"],</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "active": False</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         }</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         menu_list.append(tpl)</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> request.session[settings.PERMISSION_MENU_KEY] = menu_list  #吧所有的菜單都放在session里面</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> print("xcvxvxv", menu_list)</span>



<span style="color: #008000;">#</span><span style="color: #008000;"> 權限相關</span>
result =<span style="color: #000000;"> {}
</span><span style="color: #0000ff;">for</span> item <span style="color: #0000ff;">in</span><span style="color: #000000;"> permission_list:
    group_id </span>= item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__group_id</span><span style="color: #800000;">"</span><span style="color: #000000;">]
    url </span>=item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__url</span><span style="color: #800000;">"</span><span style="color: #000000;">]
    code </span>= item[<span style="color: #800000;">"</span><span style="color: #800000;">permissions__codes</span><span style="color: #800000;">"</span><span style="color: #000000;">]
    </span><span style="color: #0000ff;">if</span> group_id <span style="color: #0000ff;">in</span><span style="color: #000000;"> result:
        </span><span style="color: #008000;">#</span><span style="color: #008000;">如果在說明url和code已經生成了</span>
        result[group_id][<span style="color: #800000;">"</span><span style="color: #800000;">codes</span><span style="color: #800000;">"</span><span style="color: #000000;">].append(code)
        result[group_id][</span><span style="color: #800000;">"</span><span style="color: #800000;">urls</span><span style="color: #800000;">"</span><span style="color: #000000;">].append(url)
    </span><span style="color: #0000ff;">else</span><span style="color: #000000;">:
        </span><span style="color: #008000;">#</span><span style="color: #008000;">如果不在就添加進去</span>
        result[group_id] =<span style="color: #000000;">{
            </span><span style="color: #800000;">"</span><span style="color: #800000;">codes</span><span style="color: #800000;">"</span><span style="color: #000000;">:[code,],
            </span><span style="color: #800000;">"</span><span style="color: #800000;">urls</span><span style="color: #800000;">"</span><span style="color: #000000;">:[url]
        }
</span><span style="color: #008000;">#</span><span style="color: #008000;"> print(result)</span>
<span style="color: #008000;">#</span><span style="color: #008000;">吧所有權限中的url字典放到session中</span>
request.session[settings.PERMISSION_URL_DICT_KEY] =<span style="color: #000000;"> result


</span><span style="color: #008000;">#</span><span style="color: #008000;"> # 打印的結果如下</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> result = {</span>
<span style="color: #008000;">#</span><span style="color: #008000;">     1: {</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         "codes": ["list", "add", "del", "edit"]</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         "urls": [</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/",</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/add" ,</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/del(\d+)/ ",</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/userinfo/edit(\d+)/ ",</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         ]</span>
<span style="color: #008000;">#</span><span style="color: #008000;">     },</span>
<span style="color: #008000;">#</span><span style="color: #008000;">     2: {</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         "codes": {"list", "add", "del", "edit"}</span>
<span style="color: #008000;">#</span><span style="color: #008000;">          "urls": [</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/order",</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/order/add" ,</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/order/del(\d+)/ ",</span>
<span style="color: #008000;">#</span><span style="color: #008000;">             "/order/edit(\d+)/ ",</span>
<span style="color: #008000;">#</span><span style="color: #008000;">         ]</span>
<span style="color: #008000;">#</span><span style="color: #008000;">     }</span>
<span style="color: #008000;">#</span><span style="color: #008000;"> }</span></pre>
復制代碼

 

 

 

   五、中間件
      - 在setting里設置白名單(不用權限就可以訪問)

復制代碼
#白名單
VALID_URL = [
    "/login/",
    "/admin.*/",
    "/index/"
]

# ====rabc
PERMISSION_URL_DICT_KEY="permissions_url_dict"
PERMISSION_MENU_KEY
= "menu_list"

復制代碼

 

復制代碼
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    'rbac.middlewears.rbac.Middle',
]
復制代碼

 


      - 獲取當前的url請求
      - 獲取session保存的權限信息

      - 循環url進行正則匹配,如果匹配成功就有權訪問,不成功就無法訪問

用中間件的時候記得要在settings里面配置一下:

 

復制代碼
#!usr/bin/env python
# -*- coding:utf-8 -*-
import re
from django.shortcuts import render,HttpResponse,redirect
from django.conf import settings
class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()
</span><span style="color: #0000ff;">def</span> <span style="color: #800080;">__call__</span><span style="color: #000000;">(self, request):
    response </span>=<span style="color: #000000;"> None
    </span><span style="color: #0000ff;">if</span> hasattr(self, <span style="color: #800000;">'</span><span style="color: #800000;">process_request</span><span style="color: #800000;">'</span><span style="color: #000000;">):
        response </span>=<span style="color: #000000;"> self.process_request(request)
    </span><span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> response:
        response </span>=<span style="color: #000000;"> self.get_response(request)
    </span><span style="color: #0000ff;">if</span> hasattr(self, <span style="color: #800000;">'</span><span style="color: #800000;">process_response</span><span style="color: #800000;">'</span><span style="color: #000000;">):
        response </span>=<span style="color: #000000;"> self.process_response(request, response)
    </span><span style="color: #0000ff;">return</span><span style="color: #000000;"> response

class Middle(MiddlewareMixin):
def process_request(self,request):
#獲取當前的url請求
current_url = request.path_info #拿到當前的路徑
# print(request.path,current_url)
#獲取Session中保存當前用戶的權限,
# request.session.get("permissions_url_list")
# 如果當前的路徑和session里面保存的url一樣就break了,如果不一樣就說明無權訪問
for url in settings.VALID_URL:
# print(url,current_url)
if re.match(url,current_url):
return None #如果url是表名單白名單里面的,就讓直接走后面的

    permission_dict </span>=<span style="color: #000000;"> request.session.get(settings.PERMISSION_URL_DICT_KEY)
    </span><span style="color: #008000;">#</span><span style="color: #008000;">在初始化的時候把url以字典的顯示存在了session里面,現在獲取的也就是一個字典了</span>
    <span style="color: #008000;">#</span><span style="color: #008000;"> print("==========",permission_dict)</span>
    flag =<span style="color: #000000;"> False
    </span><span style="color: #0000ff;">for</span> group_id,code_url <span style="color: #0000ff;">in</span><span style="color: #000000;"> permission_dict.items():
        </span><span style="color: #0000ff;">for</span> url <span style="color: #0000ff;">in</span> code_url[<span style="color: #800000;">"</span><span style="color: #800000;">urls</span><span style="color: #800000;">"</span><span style="color: #000000;">]:
            regax </span>= <span style="color: #800000;">"</span><span style="color: #800000;">^{0}$</span><span style="color: #800000;">"</span><span style="color: #000000;">.format(url)
            </span><span style="color: #008000;">#</span><span style="color: #008000;"> print(regax,current_url)</span>
            <span style="color: #0000ff;">if</span><span style="color: #000000;"> re.match(regax,current_url):
                </span><span style="color: #008000;">#</span><span style="color: #008000;">match只要是..開頭的都能匹配到,多以的加個^和$符</span>
                request.permission_code_list=code_url[<span style="color: #800000;">"</span><span style="color: #800000;">codes</span><span style="color: #800000;">"</span><span style="color: #000000;">]
                flag </span>=<span style="color: #000000;"> True
                </span><span style="color: #0000ff;">break</span>
        <span style="color: #0000ff;">if</span> flag:  <span style="color: #008000;">#</span><span style="color: #008000;">跳出外層循環</span>
            <span style="color: #0000ff;">break</span>
    <span style="color: #0000ff;">if</span> <span style="color: #0000ff;">not</span><span style="color: #000000;"> flag:
        </span><span style="color: #0000ff;">return</span> HttpResponse(<span style="color: #800000;">"</span><span style="color: #800000;">無權訪問</span><span style="color: #800000;">"</span><span style="color: #000000;">)


</span><span style="color: #0000ff;">def</span><span style="color: #000000;"> process_response(self,request,response):
    </span><span style="color: #0000ff;">return</span> response</pre>
復制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM