前言(借鑒老師筆記)
RBAC(Role-Based Access Control,基于角色的訪問控制)就是用戶通過角色與權(quán)限進行關(guān)聯(lián)。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權(quán)限。這樣,就構(gòu)造成“用戶-角色-權(quán)限”的授權(quán)模型。在這種模型中,用戶與角色之間,角色與權(quán)限之間,一般者是多對多的關(guān)系。
簡單的權(quán)限:如下就是一個簡單的權(quán)限設(shè)計模式,其中包含了用戶表,角色表,權(quán)限表。

稍微復(fù)雜一點的權(quán)限,可能設(shè)計到用戶表、權(quán)限表、角色表、用戶組表、額外的權(quán)限表,在django中提供了這一些列的權(quán)限相關(guān)模型,關(guān)于權(quán)限設(shè)計中表的關(guān)聯(lián)關(guān)系如下:

)
1. Django的權(quán)限項
Django用permission對象存儲權(quán)限項,每個model默認(rèn)都有三個permission,即add model, change model和delete model。例如,定義一個名為學(xué)生Student模型,當(dāng)遷移表后,會在auth_permission中自動創(chuàng)建相應(yīng)的三個permission:add_student, change_student和delete_student。Django還允許自定義permission。

2. 創(chuàng)建權(quán)限
1) 自定義權(quán)限
在自定義模型的Meta元中添加permissions參數(shù),自定義權(quán)限的名稱(‘codename’,‘name’)即codename為權(quán)限名,name為權(quán)限的描述。在數(shù)據(jù)庫的auth_permission表中還有一個content_type字段,其表示prmission屬于哪個model
from django.db import models
class Users(AbstractUser):
"""
管理員---拓展User表
"""
class Meta:
permissions = (
('add_user_per', '添加用戶權(quán)限'),
('del_user_per', '刪除用戶權(quán)限'),
('change_user_per', '修改用戶權(quán)限'),
('sel_user_per', '查詢用戶權(quán)限')
)
并在settings.py文件中添加如下設(shè)置:
AUTH_USER_MODEL = 'users.Users'
注意:在數(shù)據(jù)庫的auth_permission表中,會新增權(quán)限,包括自帶的對Users管理的權(quán)限,和自定義的四個權(quán)限。
如下所示:
[圖片上傳失敗...(image-ee6095-1537444192584)]
2)創(chuàng)建權(quán)限
上面的方法是在定義模型的時候自定義權(quán)限,也可理解為創(chuàng)建系統(tǒng)的內(nèi)置權(quán)限,如果涉及到在業(yè)務(wù)邏輯中創(chuàng)建權(quán)限,則可以通過Permission模型來創(chuàng)建權(quán)限
url(r'^add_user_permission/', views.add_user_permission,name='add_user_permission'),
from django.contrib.auth.models import Permission
from django.contrib.contenttypes.models import ContentType
from django.http import HttpResponse
from users.models import Users
def add_user_permission(request):
if request.method == 'GET':
# 獲取當(dāng)前Users模型的id值
content_type = ContentType.objects.get_for_model(Users)
# codename為權(quán)限名,name為描述,content_type為當(dāng)前權(quán)限屬于哪一個模型的ID
Permission.objects.create(codename='add_other_user_permission',
name='添加其他用戶權(quán)限',
content_type=content_type)
return HttpResponse('創(chuàng)建權(quán)限成功')
3.分配權(quán)限
1)給用戶直接添加某種權(quán)限
采用直接分配權(quán)限的方法,給用戶添加額外的權(quán)限既用戶表Users和權(quán)限Permission模型以及中間表user_permission之間的關(guān)聯(lián)關(guān)系。用戶Users模型和權(quán)限Permission之間是ManyToManyField()多對多關(guān)聯(lián)關(guān)系,關(guān)聯(lián)字段為user_permission。
語法:
添加權(quán)限:user對象.user_permission.add(permission對象1, permission對象2)
刪除權(quán)限:user對象.user_permission.remove(permission對象1, permission對象2)
清空權(quán)限:user對象.user_permission.clear()
url(r'^add_permission/', views.add_permission, name='add_permission'),
from django.contrib.auth.models import Permission, User
def add_permission(request):
if request.method == 'GET':
# 獲取id=1d的用戶對象
user = Users.objects.get(id=1)
# 給該用戶添加權(quán)限
pers = Permission.objects.filter(codename__in=['add_user_per', 'del_user_per'])
for per in pers:
# 添加用戶權(quán)限
user.user_permissions.add(per)
#刪除權(quán)限
# user.user_permissions.remove(per)
# 清空權(quán)限
user.user_permissions.clear()
return HttpResponse('創(chuàng)建權(quán)限成功')
2)創(chuàng)建組并分配對應(yīng)組的權(quán)限
給組添加權(quán)限,涉及到組group表和permission權(quán)限表,以及中間關(guān)聯(lián)表。其為ManyToManyFiled()關(guān)聯(lián)關(guān)系,關(guān)聯(lián)字段為permissions 語法:
添加權(quán)限:group對象.permissions.add(permission對象1, permission對象2)
刪除權(quán)限:group對象.permissions.remove(permission對象1, permission對象2)
清空權(quán)限:group對象.permissions.clear()
url(r'^group_permission/', views.group_permission, name='group_permission'),
def group_permission(request):
if request.method == 'GET':
# 創(chuàng)建超級管理用戶組并給用戶組增加對用戶進行CRUD的權(quán)限
super_group = Group.objects.create(name='超級管理員')
pers = Permission.objects.filter(codename__in=['add_user_per', 'del_user_per', 'change_user_per', 'sel_user_per'])
for per in pers:
# 添加超級用戶組的權(quán)限
super_group.permissions.add(per)
# 刪除超級組的權(quán)限
super_group.permissions.remove(per)
# 清空組的權(quán)限
super_group.permissions.clear()
return HttpResponse('創(chuàng)建組權(quán)限')
3)分配用戶和權(quán)限組
給用戶添加組權(quán)限,涉及到組group表和user用戶表,以及中間關(guān)聯(lián)表。其為ManyToManyFiled()關(guān)聯(lián)關(guān)系,關(guān)聯(lián)字段為groups 語法:
添加權(quán)限:user對象.groups.add(groups對象1, groups對象2)
刪除權(quán)限:user對象.groups.remove(groups對象1, groups對象2)
清空權(quán)限:user對象.groups.clear()
url(r'^user_group/', views.user_group, name='user_group'),
def user_group(request):
if request.method == 'GET':
# 給id為1的用戶分配超級管理員組的權(quán)限
# 獲取超級管理員組group對象
super_group = Group.objects.get(name='超級管理員')
# 獲取id=1d的用戶對象
user = Users.objects.get(id=1)
# 添加超級用戶組的權(quán)限
user.groups.add(super_group)
# 刪除超級組的權(quán)限
# user.groups.remove(super_group)
# 清空組的權(quán)限
# user.groups.clear()
return HttpResponse('創(chuàng)建用戶組權(quán)限')
4. 檢測用戶是否有某權(quán)限,和所有權(quán)限,組權(quán)限
語法:用戶對象.has_perm('模型名.權(quán)限codename')
查詢用戶所有的權(quán)限:user.get_all_permissions()方法列出用戶的所有權(quán)限,返回值是permission name
查詢用戶的組權(quán)限:user.get_group_permissions()方法列出用戶所屬group的權(quán)限,返回值是permission name
def user_permission(request):
if request.method == 'GET':
# 獲取id=1d的用戶對象
user = Users.objects.get(id=1)
# 查看用戶的所有權(quán)限
all_perm = user.get_all_permissions()
# 查看用戶的組權(quán)限
group_perm = user.get_group_permissions()
# 查詢用戶是否有add_user_per權(quán)限
if user.has_perm('users.add_user_per'):
return HttpResponse('用戶有add_user_per權(quán)限')
else:
return HttpResponse('用戶沒有add_user_per權(quán)限')
5. 權(quán)限校驗,使用permission_required裝飾器
使用permission_required對權(quán)限進行校驗,如果沒有當(dāng)前登錄系統(tǒng)的用戶沒有該權(quán)限則跳轉(zhuǎn)到登錄頁面,如果當(dāng)前用戶有該權(quán)限,則進行訪問對應(yīng)的視圖函數(shù)。
語法:@permission_required('應(yīng)用app名.權(quán)限名codename')
url(r'^add_user_html/', views.add_user_html, name='add_user_html'),
from django.contrib.auth.decorators import permission_required
@permission_required('users.add_users')
def add_user_html(request):
if request.method == 'GET':
return HttpResponse('該方法需要添加用戶權(quán)限才可訪問')
6. 測試
定義登錄的路由,并實現(xiàn)登錄操作,當(dāng)用戶登錄后,再次訪問add_user_html路由地址,則可以訪問到對應(yīng)的視圖函數(shù),如果用戶沒有登錄則因為權(quán)限問題訪問不了add_user_html路由對應(yīng)的視圖函數(shù)。
7. 首頁index.html中通過權(quán)限控制按鈕
在模版中使用:模版中使用全局變量perms存儲當(dāng)前用戶的所有權(quán)限。通過{{ perms.應(yīng)用名 }}可打印出所有的權(quán)限。
在模板中也可以直接通過{{ user }}獲取當(dāng)前登錄系統(tǒng)的用戶信息。
使用語法格式:
{% if perms.應(yīng)用名.權(quán)限標(biāo)識 %}
<!-- 這里是有權(quán)限才顯示的內(nèi)容 -->
{% endif %}
首頁index.html中如下控制按鈕的權(quán)限:
{% extends 'base.html' %}
{% block title %}
首頁
{% endblock %}
{% block content %}
<!--模版中使用全局變量perms存儲當(dāng)前用戶的所有權(quán)限-->
{{ perms.users }}
<!--判斷當(dāng)前用戶是否為超級管理員-->
{{ user.is_superuser }}
{% if user.is_superuser or perms.users.add_user_per %}
<p>添加用戶管理</p>
{% endif %}
{% if user.is_superuser or perms.users.del_user_per %}
<p>刪除用戶管理</p>
{% endif %}
{% if user.is_superuser or perms.users.change_user_per %}
<p>修改用戶管理</p>
{% endif %}
{% if user.is_superuser or perms.users.sel_user_per %}
<p>查詢用戶管理</p>
{% endif %}
{% endblock %}