一、什么是rbac
rbac翻譯意思就是(Role-Based Access Contro)基于角色的權(quán)限控制
十載的潢川網(wǎng)站建設(shè)經(jīng)驗(yàn),針對(duì)設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對(duì)一服務(wù),響應(yīng)快,48小時(shí)及時(shí)工作處理。成都營(yíng)銷網(wǎng)站建設(shè)的優(yōu)勢(shì)是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動(dòng)調(diào)整潢川建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)公司從事“潢川網(wǎng)站設(shè)計(jì)”,“潢川網(wǎng)站推廣”以來,每個(gè)客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。
二、優(yōu)勢(shì)
1.將用戶和權(quán)限的關(guān)系
2.易擴(kuò)展,易于維護(hù)
比如張三李四需要用客戶列表訪問權(quán)限,如果上百個(gè)用戶,單獨(dú)分配權(quán)限會(huì)麻煩,如果單獨(dú)放客戶列表權(quán)限在銷售角色里面,張三李四放到銷售角色里就OK了
三、RBAC流程圖
第一張:用戶表
第二張:角色表
第三張表:用戶表和角色表多對(duì)多的關(guān)系,一個(gè)用戶可以有多個(gè)角色
第四張表:權(quán)限表
第五張表:權(quán)限表和角色表多對(duì)多的關(guān)系,多個(gè)權(quán)限可以放到一個(gè)角色里面
四、效果圖
五、本章案例
背景:開發(fā)一個(gè)固定資產(chǎn)管理系統(tǒng)
實(shí)現(xiàn)功能:根據(jù)不同用戶登陸分配不同權(quán)限,jack是CTO這個(gè)角色,CTO對(duì)所有頁面有增刪改查的權(quán)限,當(dāng)jack登陸的時(shí)候,顯示有增刪改查的按鈕。當(dāng)?shù)顷憀ucy,因?yàn)槭荂OO的權(quán)限,有所有頁面查詢的權(quán)限,只能查看,無法添加修改刪除。
1.在django中把rbac做成組件,到別的項(xiàng)目也可以直接拿來用
2.在項(xiàng)目中新創(chuàng)建一個(gè)名為rbac應(yīng)用,創(chuàng)建命令startapp rbac
3.在rbac應(yīng)用里mode.pyl寫ORM,分別是賬號(hào)表,角色表,權(quán)限表,權(quán)限組表
from django.db import models
# Create your models here.
class Account(models.Model):
name=models.CharField(max_length=32)
pwd=models.CharField(max_length=32)
roles=models.ManyToManyField(to="Role")
def __str__(self): return self.name
class Role(models.Model):
title=models.CharField(max_length=32)
permissions=models.ManyToManyField(to="Permission")
def __str__(self): return self.title
class Permission(models.Model):
title=models.CharField(max_length=32)
url=models.CharField(max_length=32)
action=models.CharField(max_length=32,default="")
group=models.ForeignKey("PermissionGroup",default=1,on_delete=models.CASCADE)
def __str__(self):return self.title
class PermissionGroup(models.Model):
title = models.CharField(max_length=32)
def __str__(self): return self.title
4.在rdac的admin文件中添加下面數(shù)據(jù),為了后臺(tái)管理
from django.contrib import admin
from .models import *
class PerConfig(admin.ModelAdmin):
list_display = ["title","url","group","action"]
admin.site.register(Account)
admin.site.register(Role)
admin.site.register(Permission,PerConfig)
admin.site.register(PermissionGroup)
5.在后臺(tái)分別對(duì)應(yīng)寫入4張表數(shù)據(jù)
這是權(quán)限表,這里可以理解為一個(gè)URL等于一個(gè)權(quán)限
6.開始寫組件
在rbac應(yīng)用中,創(chuàng)建一個(gè)service的python包,然后在下面創(chuàng)建perssions.py文件
###############################在session注冊(cè)權(quán)限列表##############################
def initial_session(user,request):
#獲取當(dāng)前用戶所在的所有角色擁有的權(quán)限url,組id,動(dòng)作,去掉重復(fù)
permissions = user.roles.all().values("permissions__url","permissions__group_id","permissions__action").distinct()
#把結(jié)果放到一個(gè)字典中
permission_dict={}
for item in permissions:
gid=item.get('permissions__group_id')
#判斷當(dāng)前組id是否已經(jīng)存在到字典中
if not gid in permission_dict:
#加逗號(hào)是因?yàn)榭紤]還有數(shù)據(jù)
#permission_dict{1:{"url":["/device_list/"],"action":"[search"]},2:{"url":["/device_list/"],"action":["search"}]}
permission_dict[gid]={
"urls":[item["permissions__url"],],
"actions":[item["permissions__action"],]
}
else:
permission_dict[gid]["urls"].append(item["permissions__url"])
permission_dict[gid]["actions"].append(item["permissions__action"])
request.session['permission_dict'] = permission_dict
然后再創(chuàng)建rbac.py,寫一個(gè)類,最終寫到setting.py的MIDDLEWARE。
import re
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse,redirect
class ValidPermission(MiddlewareMixin):
def process_request(self,request):
# 當(dāng)前訪問路徑
current_path = request.path_info
# 檢查是否屬于白名單,如果是下面路徑url不用校驗(yàn)
valid_url_list=["/login/","/reg/","/admin/.*","/index/",'/logout/']
for valid_url in valid_url_list:
ret=re.match(valid_url,current_path)
if ret:
return None
# 校驗(yàn)是否登錄,這步是為了讓用戶去登陸,而不是返回一個(gè)沒有權(quán)限的頁面
user_id=request.session.get("user_id")
if not user_id:
return redirect("/index/")
# 校驗(yàn)url
permission_dict=request.session.get("permission_dict")
for item in permission_dict.values():
urls=item['urls']
for reg in urls:
reg="^%s$"%reg
ret=re.match(reg,current_path)
if ret:
request.actions=item['actions']
return None
return HttpResponse("沒有訪問權(quán)限!")
7.寫views.py文件,當(dāng)用戶在登陸頁面登陸發(fā)送賬號(hào)密碼過來時(shí),進(jìn)行校驗(yàn),如果存在賬號(hào)表中,就在session會(huì)話中注冊(cè)這個(gè)用戶id,調(diào)用rbac組件,如果通過了就返回頁面
#登陸函數(shù)
def login(request):
if request.method=="POST":
user=request.POST.get("user")
pwd=request.POST.get("pwd")
#獲取Account表里面去找有沒有當(dāng)前的用戶名和密碼
user=Account.objects.filter(name=user,pwd=pwd).first()
if user:
############################### 在session中注冊(cè)用戶ID######################
request.session["user_id"]=user.pk
#調(diào)用組件
initial_session(user,request)
return redirect("/device_list/")
return render(request,"index.html")
8.在view.py視圖文件中添加下面代碼,Per(request.actions)獲取當(dāng)前用戶動(dòng)作
class Per(object):
def __init__(self,actions):
self.actions=actions
def add(self):
return "add" in self.actions
def delete(self):
return "delete" in self.actions
def edit(self):
return "edit" in self.actions
def list(self):
return "search" in self.actions
def device_list(request):
ret = models.Device.objects.all()
#在前端頁面顯示用戶名
per = Per(request.actions)
return render(request, 'device/device_list.html', locals())
9.前端頁面寫模板語言,下面代碼是寫在form表單
#判斷用戶是否有add添加權(quán)限,如果有則顯示按鈕,否則不顯示
{% if per.add %}
新增
{% endif %}
同樣是判斷是否有刪除和編輯權(quán)限
{% if per.delete %}
刪除
{% endif %}
{% if per.edit %}
編輯
{% endif %}
10.顯示圖,登陸jack用戶
再登陸luyc用戶
可以看到lucy沒有添加刪除編輯的按鈕,就算成功了。
補(bǔ)充一點(diǎn),url和views.py都寫在項(xiàng)目中,不是寫在應(yīng)用中喔。