RBAC(Role-Based Access Control,基於角色的訪問控制)就是用戶通過角色與權限進行關聯。簡單地說,一個用戶擁有若干角色,每一個角色擁有若干權限。這樣,就構造成“用戶-角色-權限”的授權模型。在這種模型中,用戶與角色之間,角色與權限之間,一般者是多對多的關系。
簡單的權限:如下就是一個簡單的權限設計模式,其中包含了用戶表,角色表,權限表。

稍微復雜一點的權限,可能設計到用戶表、權限表、角色表、用戶組表、額外的權限表,在django中提供了這一些列的權限相關模型,關於權限設計中表的關聯關系如下:

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

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