rbac:基於角色的權限訪問控制(Role-Based Access Control)。html
rbac的主要流程:給每一個角色賦予不一樣的權限,是這個角色的員工都有這個角色的全部權限。一個角色能夠有多我的員擔任,一個員工能夠擔任多個角色(好比部門經理、業務員等)。當員工成功登錄系統時,系統須要獲取這個員工的多有權限,並放到一個列表裏面。而後員工在訪問每一個權限url時,系統須要進行判斷該員工有沒有這個權限進行這項操做。如何判斷?就是循環這個員工的全部權限,看有沒有對應的權限。這裏用到了re模塊裏面的match方法。django
以下代碼:session
# 須要先登錄,拿到該員工的權限列表並去重
def login(request): if request.method=="GET": return render(request,"login.html") else: user=request.POST.get("user") pwd=request.POST.get("pwd") user=UserInfo.objects.filter(name=user,pwd=pwd).first() if user: # 驗證成功以後作什麼? request.session["user_id"]=user.pk # 設置session # 當前登陸用戶的全部權限, distinct()是去掉重複的權限 permission_info=user.roles.all().values("permissions__url","permissions__title").distinct() temp=[] # 該員工的所有權限url列表 for i in permission_info: temp.append(i["permissions__url"]) request.session["permission_list"]=temp # {"user_id":1,"permission_list":['/users/','/orders/']} return HttpResponse("登陸成功!") else: return redirect("/login/")
登錄成功以後,判斷查看用戶操做權限app
from django.shortcuts import HttpResponse def users(request): # //users/ current_path = request.path_info # 拿到訪問的路徑 permission_list = request.session.get("permission_list") # 取session,從session表裏面取到這個員工的全部權限 ['/order/', '/users/']
if not permission_list: # 用戶沒有登錄,取不到權限列表
return HttpResponse("login.html") # /users/edit/3 爲何要用正則,由於/users/edit/3 與/users/edit/(/d+)不能直接匹配 import re flag = False # 加上標誌位 for permission_url in permission_list: ret = re.match(permission_url, current_path) # 用正則去匹配具體的路徑,成功則返回對象, 不然返回None if ret: # 若是返回對象 flag = True break if not flag: return HttpResponse("沒有訪問權限") return HttpResponse("用戶列表") # 有權限
接下來經過中間件來實現這個功能url
再建立一個應用名字叫作rbac(固然也能夠放到同一個應用裏面),這個應用裏面建立一個包service,包裏建立一個名字爲permission_li.py的文件。spa
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import redirect,HttpResponse,render class M1(MiddlewareMixin): def process_request(self,request): # //users/ current_path = request.path_info # 拿到訪問的路徑 permission_list = request.session.get("permission_list") # 從session表裏面取到這個員工的全部權限 ['/order/', '/users/'] # /users/edit/3 爲何要用正則,由於/users/edit/3 與/users/edit/(/d+)不能直接匹配 import re flag = False # 加上標誌位 for permission_url in permission_list: ret = re.match(permission_url, current_path) # 用正則去匹配具體的路徑,成功則返回對象, 不然返回None if ret: # 若是返回對象 flag = True break if not flag: return HttpResponse("沒有訪問權限")
settings.py裏面code
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.service.permission_li.M1', # 加在這裏 ]
接下來的問題就是,加上中間件以後,登錄頁面也沒有權限訪問了。csrf
咱們添加白名單,登錄、註冊和admin頁面加里便可。htm
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import redirect,HttpResponse,render class M1(MiddlewareMixin): def process_request(self,request): pass #/admin/login/?next=/admin/ current_path = request.path_info valid_url_menu=["/login/","/reg/","/admin/.*"] import re for valid_url in valid_url_menu: ret=re.match(valid_url,current_path) if ret: return None permission_list = request.session.get("permission_list") if not permission_list: return redirect("/login/") # /users/edit/3 import re flag = False for permission_url in permission_list: ret = re.match(permission_url, current_path) if ret: flag = True break if not flag: return HttpResponse("沒有權限")