需求分析:
1.判斷用戶是否登陸,未登陸就不能進入其他頁面
2.為用戶分配不同的權限,用戶的操作只能在權限范圍之內
3.將用戶可操作的權限顯示在頁面山,點擊能進入該頁面操作
模型表的建立
1.對每個用戶建立角色,每個角色有着不同的權限
2.權限的字段要設有相應的權限操作路徑和操作名稱
3.用戶可有多個角色,每個角色可有多個用戶。用戶和角色:ManyToMany
4.每個角色可有多個權限,同一個權限也可被多個用戶使用 角色和權限:ManyToMany
from django.db import models # Create your models here. class UseInfo(models.Model): username=models.CharField(max_length=25,verbose_name='用戶名') passwd=models.CharField(max_length=25,verbose_name='密碼') roles=models.ManyToManyField(to="Role",verbose_name='角色') def __str__(self): return self.username class Role(models.Model): title=models.CharField(max_length=32,verbose_name='角色') permissions=models.ManyToManyField(to="Permission",verbose_name='權限') def __str__(self): return self.title class Permission(models.Model): title=models.CharField(max_length=32,verbose_name="權限") url=models.CharField(max_length=255,verbose_name="執行路徑") code=models.CharField(max_length=32,verbose_name='權限代號') def __str__(self): return self.title
2.用戶登陸后,設置session
用戶登陸之后,將用戶id和權限注冊到session中
if user: # 向session注入user信息 request.session["user_id"] = user.pk # 向session注入當前登錄人的權限列表 from Rbac.service.rbac import init_permission init_permission(user,request) return redirect("/index/")
用建個py文件注冊用戶權限
def init_permission(user,request): ##多對多的關系,因此使用all permissions=user.roles.all().values("permissions__url","permissions__title","permissions__code") #print(permissions) #< QuerySet[{'permissions__url': '/Xadmin/Rbac/useinfo/', 'permissions__title': '查看用戶', 'permissions__code': 'list'} permission_list=[] for perm in permissions: permission_list.append(perm.get("permissions__url")) #將權限注冊到session中 request.session["permission_list"] = permission_list
3.設置中間件
對用戶的請求做出判斷,判斷出該用戶當前請求是否符合要求,對於用戶的每次請求,設置中間件來判斷
1.登陸,主頁,這些路徑不設置驗證,讓所有用戶都可訪問
white_url=["/login/","/index/"] if current_path in white_url: return None
2.進入查看,修改頁面時,判斷是否有這些權限
['/Xadmin/Rbac/useinfo/', '/Xadmin/Rbac/useinfo/add/', '/Xadmin/Rbac/useinfo/change/(\\d+)/', '/Xadmin/Rbac/useinfo/del/(\\d+)/'] permission_list=request.session.get("permission_list") print("他是:",permission_list) if current_path not in permission_list: return HttpResponse("沒有權限")
但是在點擊編輯和刪除時,卻顯示沒有權限,原因?
點編輯和刪除時由於有參數,回顯示具體的值,/Xadmin/Rbac/useinfo/change/1/,而permission_list中給卻是'/Xadmin/Rbac/useinfo/change/(\\d+)/'
因此匹配不上,顯示無權限。應該用正則匹配完成
permission_list=request.session.get("permission_list") for permission in permission_list: ret=re.search(permission,current_path) if ret:return None return HttpResponse("沒有權限")
此時更換用戶,此用戶只有查看權限:
['/Xadmin/Rbac/useinfo/', '/Xadmin/Rbac/role/']
在訪問/Xadmin/Rbac/role/add/時,卻能訪問成功,原因?
在匹配時,匹配的規則是/Xadmin/Rbac/role/,匹配對象/Xadmin/Rbac/role/add/,
匹配的結果為/Xadmin/Rbac/role/,ret為真,會通過驗證
因此要限制匹配對象開始值和結束值
for permission in permission_list: permission="^%s$"%permission ret=re.search(permission,current_path) if ret:return None return HttpResponse("沒有權限")
3.設置admin
讓所有用戶都能進入admin,因此將admin設置到白名單中,此時若仍用下面這種該方法,會出問題
white_url=["/login/","/index/","/admin/"]
if current_path in white_url:
return None
進入admin后,會發現地址欄出現變化:/admin/login/?next=/admin/
此時在用in,則當前地址匹配不到admin,因此在匹配時,讓用正則進行匹配
white_url=["/login/","/index/","/admin/*"] for url in white_url: url="^%s"%url ret=re.search(url,current_path) if ret:return None
由於admin有參數,此時不能加$
設置中間件

4.頁面左側顯示該用戶的權限
顯示的權限名是個a標簽,當點擊時,執行該操作,因此,編輯和刪除權限不能顯示出來。
在向session中注冊時,將添加和查看的url和對應的操作名也注冊進去,但是譖言給判斷當前url時哪種操作?
可以為權限表新添個code字段,來描述url,如增加操作,就將code設置為add,顯示操作,設置為list,通過判斷code字段進行添加
def init_permission(user,request): ##多對多的關系,因此使用all permissions=user.roles.all().values("permissions__url","permissions__title","permissions__code") #print(permissions) #< QuerySet[{'permissions__url': '/Xadmin/Rbac/useinfo/', 'permissions__title': '查看用戶', 'permissions__code': 'list'} permission_list=[] menu_permission={} for perm in permissions: permission_list.append(perm.get("permissions__url")) if perm.get("permissions__code")=="list" or perm.get("permissions__code")=="add": menu_permission[ perm.get("permissions__title")]=perm.get("permissions__url") #將權限注冊到session中 request.session["permission_list"] = permission_list request.session["menu_permission"]= menu_permission
在頁面上將權限菜單顯示在左邊,應將其固定,即頁面往下拉時,該菜單仍在這個位置,要用到 position: fixed這個屬性,
對於文本內容用到overflow: auto和 position: fixed