目录
前言
目前,使用最普遍的权限管理模型正是RBAC(Role-Based Access Control)模型,中文意思就是基于角色的访问控制,基于角色的访问控制(RBAC)是实施面向企业安全策略的一种有效的访问控制方式。根据百度百科的解释是这样的,RBAC其基本思想是,对系统操作的各种权限不是直接授予具体的用户,而是在用户集合与权限集合之间建立一个角色集合。每一种角色对应一组相应的权限。一旦用户被分配了适当的角色后,该用户就拥有此角色的所有操作权限。这样做的好处是,不必在每次创建用户时都进行分配权限的操作,只要分配用户相应的角色即可,而且角色的权限变更比用户的权限变更要少得多,这样将简化用户的权限管理,减少系统的开销。这篇文章也主要是介绍基于RBAC的权限管理系统,我会从RBAC是什么、如何设计RBAC两部分来介绍。
一、RBAC是什么?
1.BRAC模型概述
RBAC模型是20世纪90年代研究出来的一种新模型,但其实在20世纪70年代的多用户计算时期,这种思想就已经被提出,这种思想就已经被提出,直到20世纪90年代中后期,RBAC才在研究团体中得到一些重视,并先后提出了许多类型的RBAC模型。其中以美国George Mason大学信息安全技术实验室(LIST)提出的RBAC96模型最具有代表,并得到了普遍的公认。
RBAC认为权限的过程可以抽象概括为:判断【Who是否可以对What进行How的访问操作(Operator)】这个逻辑表达式的值是否为True的求解过程。
即将权限问题转换为Who、What、How的问题。who、what、how构成了访问权限三元组。
RBAC是把用户按角色进行归类,通过用户的角色来确定用户能否针对某项资源进行某项操作。RBAC相对于ACL最大的优势就是它简化了用户与权限的管理,通过对用户进行分类,使得角色与权限关联起来,而用户与权限变成了间接关联。
RBAC模型使得访问控制,特别是对用户的授权管理变得非常简单和易于维护,因此有广泛的应用。
但是它也有自身的缺点,那就是由于权限是以角色为载体分配的,如果某一角色下的个别用户需要进行特别的权限定制,如同加入一些其他角色的小部分权限或去除当前角色的一些权限时,RBAC就无能为力了,因为RBAC对权限的分配是角色为单位的。
2.ACL模型
在了解RBAC模型的组成之前,我们先对ACL模型做个了解。
ACL是最早也是最基本的一种访问控制机制,它的原理非常简单:每一项资源,都配有一个列表,这个列表记录的就是哪些用户可以对这项资源执行CRUD中的那些操作。当系统试图访问这项资源时,会首先检查这个列表中是否有关于当前用户的访问权限,从而确定当前用户可否执行相应的操作。
ACL是一种面向资源的访问控制模型,它的机制是围绕“资源”展开的.
The relative simplicity of ACLs means they do not need much underlying technological infrastructure to work.
由于ACL的简单性,使得它几乎不需要任何基础设施就可以完成访问控制。但同时它的缺点也是很明显的,由于需要维护大量的访问权限列表。ACL在性能上有明显的缺陷。另外,对于拥有大量用户与众多资源的应用,管理访问控制列表本身就变成非常繁重的工作。
3.RBAC的组成
在RBAC模型里面,主要有3个基础组成部分,包括有用户、角色和权限。
RBAC通过定义角色的权限,并对用户授权某个角色,从而控制用户的权限。实现了用户和权限在逻辑分离,极大地方便了权限得管理
- User(用户):每个用户都有唯一的UID,并且可以授予不同的角色
- Role(角色):每个角色都有唯一的RID,不同角色具有不同的权限
- Permission(权限):具有访问的能力
- 用户-角色映射:用户和角色之间的映射关系
- 角色-权限映射:角色和权限之间的映射关系
这些组成成分之间的关系大致如下:
那么我们再画一个图,具体看看这些关系是怎么使用的呢?
例如下图,管理员和普通用户被授予不同的权限,普通用户只能去修改和查看个人信息,而不能修改管理员身份,而管理员由于被授予所有权限,所以可以做所有操作。
除此之外,还可能出现另一种情况,一个用户可能有多种身份,那么就可能拥有更多的权限。例如一个项目经理也可以是项目架构师等等;当然一个角色也可以给多个用户,例如一个项目有多个项目组长和多个组员等。
这里需要提出的是,将用户和许可进行分离,是彼此相互独立,使权限的授权认证更加灵活。
角色和许可(权限)是多对多的关系,表示角色可以拥有多分权利,同一个权利可以授给多个角色都是非常容易理解的,想想现实生活中,当官的级别不同的权限的情景,其实这个模型就是对权限这方面的一个抽象,联系生活理解就非常容易了。
二、RBAC的3种模型
1.RBAC0
RBAC0,是最简单、最原始的实现方式,也是其他RBAC模型的基础。
2.RBAC1
基于RBAC0模型,引入了角色间的继承关系,即角色上有了上下级的区别。
角色间的继承关系可分为一般继承关系和受限继承关系。一般继承关系仅要求角色继承关系是一个绝对偏序关系,允许角色间的多继承。而受限继承关系则进一步要求角色继承关系是一个树结构,实现角色间的单继承。
这种模型适合于角色之间层次分明,可以给角色分组分层。
3.RBAC2
RBAC2,基于RBAC0模型的基础上,进行了角色的访问控制。
RBAC2中的一个基本限制是互斥角色的限制,互斥角色是指各自权限可以互相制约的两个角色。对于这类角色一个用户在某一次活动中只能被分配其中的一个角色,不能同时获得两个角色的使用权。
该模型有以下几种约束:
- 互斥角色 :同一用户只能分配到一组互斥角色集合中至多一个角色,支持责任分离的原则。互斥角色是指各自权限互相制约的两个角色。对于这类角色一个用户在某一次活动中只能被分配其中的一个角色,不能同时获得两个角色的使用权。常举的例子:在审计活动中,一个角色不能同时被指派给会计角色和审计员角色。
- 基数约束 :一个角色被分配的用户数量受限;一个用户可拥有的角色数目受限;同样一个角色对应的访问权限数目也应受限,以控制高级权限在系统中的分配。例如公司的领导人有限的;
- 先决条件角色 :可以分配角色给用户仅当该用户已经是另一角色的成员;对应的可以分配访问权限给角色,仅当该角色已经拥有另一种访问权限。指要想获得较高的权限,要首先拥有低一级的权限。就像我们生活中,国家主席是从副主席中选举的一样。
- 运行时互斥 :例如,允许一个用户具有两个角色的成员资格,但在运行中不可同时激活这两个角色。
三、RBAC的设计
这一节,我会介绍设计基于RBAC模型的权限系统的功能模块组成、流程以及数据库的设计。
角色是什么?可以理解为一定数量的权限的集合,权限的载体。例如:一个论坛系统,“超级管理员”、“版主”都是角色。版主可管理版内的帖子、可管理版内的用户等,这些是权限。要给某个用户授予这些权限,不需要直接将权限授予用户,可将“版主”这个角色赋予该用户。
当用户的数量非常大时,要给系统每个用户逐一授权(授角色),是件非常烦琐的事情。这时,就需要给用户分组,每个用户组内有多个用户。除了可给用户授权外,还可以给用户组授权。这样一来,用户拥有的所有权限,就是用户个人拥有的权限与该用户所在用户组拥有的权限之和。(下图为用户组、用户与角色三者的关联关系)
在应用系统中,权限表现成什么?对功能模块的操作,对上传文件的删改,菜单的访问,甚至页面上某个按钮、某个图片的可见性控制,都可属于权限的范畴。有些权限设计,会把功能操作作为一类,而把文件、菜单、页面元素等作为另一类,这样构成“用户-角色-权限-资源”的授权模型。而在做数据表建模时,可把功能操作和资源统一管理,也就是都直接与权限表进行关联,这样可能更具便捷性和易扩展性。(见下图)
请留意权限表中有一列“权限类型”,我们根据它的取值来区分是哪一类权限,如“MENU”表示菜单的访问权限、“OPERATION”表示功能模块的操作权限、“FILE”表示文件的修改权限、“ELEMENT”表示页面元素的可见性控制等。
这样设计的好处有二。其一,不需要区分哪些是权限操作,哪些是资源,(实际上,有时候也不好区分,如菜单,把它理解为资源呢还是功能模块权限呢?)。其二,方便扩展,当系统要对新的东西进行权限控制时,我只需要建立一个新的关联表“权限XX关联表”,并确定这类权限的权限类型字符串。
这里要注意的是,权限表与权限菜单关联表、权限菜单关联表与菜单表都是一对一的关系。(文件、页面权限点、功能操作等同理)。也就是每添加一个菜单,就得同时往这三个表中各插入一条记录。这样,可以不需要权限菜单关联表,让权限表与菜单表直接关联,此时,须在权限表中新增一列用来保存菜单的ID,权限表通过“权限类型”和这个ID来区分是种类型下的哪条记录。
到这里,RBAC权限模型的扩展模型的完整设计图如下:
随着系统的日益庞大,为了方便管理,可引入角色组对角色进行分类管理,跟用户组不同,角色组不参与授权。例如:某电网系统的权限管理模块中,角色就是挂在区局下,而区局在这里可当作角色组,它不参于权限分配。另外,为方便上面各主表自身的管理与查找,可采用树型结构,如菜单树、功能树等,当然这些可不需要参于权限分配。
四、Django实现数据库的构建
在实现最简单RBAC模型中至少需要8张表(其中一张为目录表,这张表可以不存在)
- User(用户表)
- Role(角色表)
- user2role(用户角色关系表)
- Permission(权限表)
- action(操作表)
(因为我们将权限中具体的划分出来了增删改查的功能,因为不同的角色可能对一个权限有查看功能,但不一定具有操作功能)
- permission2action(操作权限表)
(该表对权限和操作是一个多对多的关系,一个权限拥有多个操作,一个操作可能被多个权限拥有)
- permission2action2role(角色操作权限表)
(该表是真正的将角色和权限之间的关系绑定起来了)
- menu(目录表)
五、Django实现代码
urls.py
from django.contrib import admin
from django.urls import path
from rbac import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login.html', views.login),
path('index.html', views.index),
path('order.html', views.order),
path('logout.html', views.logout),
]
views.py
from django.shortcuts import render, redirect, HttpResponse
from . import models
import re
# Create your views here
class PermissionHelper(object):
def __init__(self, request, username, ):
self.request = request
self.username = username
self.current_url = request.path_info
print(self.current_url)
# 获取当前用户的所有权限
self.Permission2Action = None
# 获取在菜单中显示的权限
self.menu_leaf_list = None
# 获取所有菜单
self.menu_list = None
self.permission2action_dict = None
self.result = None
self.init_data()
def init_data(self):
permission_dict = self.request.session.get('permission_info')
if permission_dict:
self.permission2action_dict = permission_dict['permission2action_dict']
self.menu_leaf_list = permission_dict['menu_leaf_list']
self.menu_list = permission_dict['menu_list']
else:
# 获取user对应的role对象
"""
# 方式一:
# 前提:通过 ManyToManyField字段创建第三张表
# role_obj = user_obj.r.all()