1. 需求分析:
准備:創建獨立app, rbac #權限管理模塊/組件 app01 #應用
分配權限,URL
2. 數據庫設計
2.1 設計思路
第一版: 權限表: ID url title is_menu 1 /index/ 首頁 False 2 /userinfo/ 用戶列表 True 3 /userinfo/add/ 添加用戶 True 4 /userinfo/del/(\d+)/ 刪除用戶 False 5 /userinfo/edit/(\d+)/ 修改用戶 False 用戶表: ID username password .... 1 番禺 123 2 夾縫 123 3 果凍 123 4 魯寧 123 權限用戶關系表: 用戶ID 權限ID 1 1 1 2 1 3 1 4 1 5 2 1 2 2 2 3 3 1 4 1 4 2 4 3
第二版: 用戶表: ID username password .... 1 番禺 123 2 夾縫 123 3 果凍 123 4 魯寧 123 角色表: ID title 1 CEO 2 CTO 4 COO 5 部門經理 6 技術員 用戶和角色關系表: 用戶ID 角色ID 1 1 1 2 1 4 2 5 3 6 4 6 權限表: ID url title 1 /index/ 首頁 2 /userinfo/ 用戶列表 3 /userinfo/add/ 添加用戶 4 /userinfo/del/(\d+)/ 刪除用戶 5 /userinfo/edit/(\d+)/ 修改用戶 角色權限關系表: 角色ID 權限ID 1 1
2.2 創建表類app01.models.py
from django.db import models
class UserInfo(models.Model):
username=models.CharField(max_length=32,verbose_name='用戶名')
password=models.CharField(max_length=32,verbose_name='密碼')
email=models.CharField(max_length=32,verbose_name='郵件')
roles=models.ManyToManyField(to='Role',verbose_name='具有的所有角色',blank=True)
class Meta:
verbose_name_plural='用戶表'
def __str__(self):
return self.username
class Permissions(models.Model):
title=models.CharField(max_length=64,verbose_name='標題')
url=models.CharField(max_length=64,verbose_name='含規則URL')
is_menu =models.BooleanField(verbose_name='是否是菜單')
class Meta:
verbose_name_plural='權限表'
def __str__(self):
return self.title
class Role(models.Model):
title=models.CharField(max_length=32)
permissions=models.ManyToManyField(to='Permissions',verbose_name='具有的所有權限',blank=True)
class Meta:
verbose_name_plural='角色表'
def __str__(self):
return self.title
3. 權限錄入:
CEO:番禺 /userinfo/ /userinfo/add/ /userinfo/edit/(\d+)/ /userinfo/del/(\d+)/ /order/ /order/add/ /order/edit/(\d+)/ /order/del/(\d+)/ 總監:魯寧 /userinfo/ /userinfo/add/ /order/ /order/add/ 經理:腎松 /userinfo/ /order/ 業務員:腎松,文飛,成棟 /order/ PS: 去重 問題: 1. 用戶登錄 - 獲取當前用戶具有的所有角色 - 獲取當前用戶具有的所有權限 - 獲取當前用戶具有的所有權限(去重)
4. 權限梳理
a. 創建rbac app b. 創建表結構,rbac,基於角色權限控制 - 三個類 - 五張表 c. 基於Django admin錄入權限數據 python manage.py createsuperuser - root - root!2345 d. 用戶登錄程序 - 獲取當前用戶具有的所有權限(去重) - 獲取權限中的url,放置到session中 rabc.service.init_permission def init_permission(user,request): pass e. 中間件 - 白名單 - 獲取請求URL - session保存的權限信息 - 循環url,re.match(db_url, current_url)
5. rbac中的代碼:
- models.py - admin.py - service.init_permission.py #權限攻擊組件 - middlewares.rabc.py #中間件 配置文件中setting配置白名單:
VALID_URL = [ "/login/", "/admin.*" ]
6 代碼展示
6.1 E:\Django項目練習03\rbac\service\init_permissions.py
def init_permissions(user,request):
url_list = []
# 獲取user中所有的url權限
permission_url_list = user.roles.values('permissions__url', 'permissions__title', 'permissions__is_menu').distinct()
# 將url權限去重添加到url_list列表中
for item in permission_url_list:
url_list.append(item['permissions__url'])
print('url_list:',url_list)
# 定制session
request.session['permission_url_list'] = url_list
6.2 中間件setting配置
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.middlewares.rbac.RbacMiddleware' #權限管理組件引用路徑
]
6.3 rbac.py文件代碼 E:\Django項目練習03\rbac\middlewares\rbac.py
import re
from django.shortcuts import render,redirect,HttpResponse
from django.conf import settings
class MiddlewareMixin(object):
def __init__(self, get_response=None):
self.get_response = get_response
super(MiddlewareMixin, self).__init__()
def __call__(self, request):
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
if not response:
response = self.get_response(request)
if hasattr(self, 'process_response'):
response = self.process_response(request, response)
return response
class RbacMiddleware(MiddlewareMixin):
def process_request(self,request):
# 1.獲取當前的請求url:request.path_info
# 2.獲取session中保存當前用戶的權限
# request.session.get("permission_url_list")
current_url = request.path_info
# 當前請求不需要執行權限驗證
for url in settings.VALID_URL:
if re.match(url,current_url):
return None
permission_list = request.session.get("permission_url_list")
print('permission_list',permission_list)
if not permission_list:
return redirect('/login/')
flag=False
for db_url in permission_list:
regax="^{0}$".format(db_url)
if re.match(regax,current_url):
flag =True
break
if not flag:
return HttpResponse('無權訪問')
6.4 使用rbac組件 應用路徑:E:\Django項目練習03\app01\views.py
from django.shortcuts import render,redirect,HttpResponse
from app01 import models
from rbac.service.init_permissions import init_permissions
def login(request):
if request.method=="GET":
return render(request,'login.html')
else:
username=request.POST.get('user')
password=request.POST.get('pwd')
user=models.UserInfo.objects.filter(username=username,password=password).first()
if not user:
return render(request,'login.html')
else:
init_permissions(user,request) #定制session模塊
return redirect('/index/')
def index(request):
return HttpResponse('首頁頁面')
def userinfo(request):
return HttpResponse('用戶管理')
def userinfo_add(request):
return HttpResponse('添加用戶')
def order(request):
return HttpResponse('訂單管理')
def order_add(request):
return HttpResponse('添加訂單')
6.5 路由文件配置
from django.conf.urls import url
from django.contrib import admin
from app01 import views as app01_views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^login/', app01_views.login),
url(r'^index/', app01_views.index),
url(r'^userinfo/$', app01_views.userinfo),
url(r'^userinfo/add/$', app01_views.userinfo_add),
url(r'^order/$', app01_views.order),
url(r'^order/add/$', app01_views.order_add),
]
