什麼是權限:django
誰對什麼資源能作什麼操做。session
管理權限的實現有不少,這裏實現一個最簡單的管理權限的實現方式:rbac ( role based access control )app
實現的一個基本思路:url
一張user用戶表,一張role角色表,一張permission權限表spa
其中,用戶與角色是多對多的關係,角色和權限是多對多的關係設計
用戶登陸後,經過用戶能夠獲取當前登陸人的全部權限,並設置session值(request.session["permission_list"] = 值)code
而後設置中間件,在用戶登陸時,設置一個白名單,若是用戶沒有登陸就去登陸,若是登陸就直接從session中取出session_list權限列表,正則匹配這個權限列表,若是匹配上,返回None,不然,返回響應沒有訪問權限。而且用戶能夠在左側菜單查看本身的訪問權限有哪些。中間件
首先第一步:表單的設計blog
若是user用戶表藉助了auth模塊,就直接import 這張表繼承
在rbac這個APP中:(將管理權限設爲一個獨立的app(組件)) models.py
from django.db import models # Create your models here. class User(models.Model): name=models.CharField(max_length=32) pwd=models.CharField(max_length=32) roles=models.ManyToManyField("Role") def __str__(self): return self.name class Role(models.Model): title=models.CharField(max_length=32) permissions=models.ManyToManyField("Permission") def __str__(self): return self.title class Permission(models.Model): title = models.CharField(max_length=32) url = models.CharField(max_length=32) code=models.CharField(max_length=32,default="list") def __str__(self): return self.title
因爲是基於Xadmin的,因此咱們要藉助這個後臺管理,因此要將這幾張模型表註冊
在rbac app下的Xadmin.py中註冊:
from Xadmin.service.Xadmin import site,ModelXadmin from .models import User from .models import Role from .models import Permission site.register(User) site.register(Role) class PermisssionConfig(ModelXadmin): list_display = ["id","title","url","code"] site.register(Permission,PermisssionConfig)
設置中間件,而且將權限列表保存在session中
在rbac下建立一個service的package,而後在新建一個.py文件,用於放置中間件的邏輯。
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import redirect,HttpResponse,render import re class ValidPermission(MiddlewareMixin): def process_request(self,request): print("path",request.path) current_path=request.path white_list=["/login/","/reg/","/index/","/admin/*"] for ignore_url in white_list: ret=re.search(ignore_url,current_path) if ret: return None # 校驗是否登陸 user_id=request.session.get("user_id") if not user_id: return redirect("/login/") # 校驗是否擁有相應權限 permission_list=request.session.get("permission_list") print("permission_list",permission_list) for permission in permission_list: permission="^%s$"%permission ret=re.search(permission,current_path) if ret: return None return HttpResponse("沒有訪問權限!")
登陸成功後,校驗經過後,執行取值和給session賦值:(將這個過程封裝到一個.py文件中,哪兒須要直接import便可)
def init_session_permission(user,request): permissions = user.roles.all().values("permissions__url","permissions__code","permissions__title").distinct() print("permissions",permissions) permission_list = [] menu_permission_dict={} for permission in permissions: permission_list.append(permission.get("permissions__url")) if permission.get("permissions__code")=="list": menu_permission_dict[permission.get("permissions__title")]=permission.get("permissions__url") request.session["permission_list"] = permission_list request.session["menu_permission_dict"] = menu_permission_dict
備註:要對篩選的結果進行去重操做。由於一個用戶會有多個role。
在用戶左側菜單展現可訪問的頁面
左側展現頁面:首先一點,咱們能夠給用戶展現權限中的那些url,增刪改查中,改刪是有動態參數的,沒法展現,而添加頁面顯得有些多餘,因此咱們能夠將全部的權限路徑中屬於展現的url過濾出來,而後加入左側菜單欄中,爲了方便快捷,咱們能夠在這個permission權限表中,增長一個字段,叫code,咱們能夠將增刪改查設置爲四類,而後在登陸成功,設置session值時,對查這個url進行過濾,單獨保存在一個session中,而後咱們能夠在相應頁面中直接取值,便可,大大的方便了展現信息的代碼冗餘和可複用性。具體的HTML頁面中,咱們能夠設置到一個母版中,而後用戶就能夠在不一樣的頁面直接經過繼承就能夠實現左側菜單欄的效果。
具體的HTML的實現:
<div class="menu"> <div class="panel panel-danger"> <div class="panel-heading">Panel heading without title</div> <div class="panel-body"> {% for title,url in request.session.menu_permission_dict.items %} <p><a href="{{ url }}">{{ title }}</a></p> {% endfor %} </div> </div> </div>