RBAC笔记

Q0.有哪些概念需要知道?

一些概念的具体定义如下

  • 用户(user): 和计算机系统交互的人(在许多设计方案中,单个用户可能拥有多个登录标识(ID),这些标识可能同时处于活跃状态,但身份验证机制可以使多个标识匹配到某个具体的人,即用户对于计算机系统来说具有唯一性)
  • 主体(subject): 一个代表用户行为的计算机进程(可以看成是用户的agent)
  • 客体(object): 计算机系统中任意可访问的资源
  • 操作(operation): 由客体触发的活动进程
  • 权限(permission): 系统中授权可以执行的动作,即客体和操作的组合
  • 角色: 不同权限或角色(职责)的集合
  • 会话(session) : 用户和系统交互的实例

Q1.什么是RBAC?

  1. 请自行参考百度百科和维基百科
  2. 核心概念:用户通过指派角色而获取相应的权限,而非直接把权限赋予用户

Q2.RBAC为什么通过角色来为用户分配权限,而不直接把权限赋予用户?

通常用户和权限的关系变更频繁,而角色和权限的关系则相对稳定。例如,系统中某个用户辞职了,只需要将系统中该用户的角色授权撤销即可。

Q3.RBAC0,RBAC1,RBAC2,RBAC3有什么联系?


RBAC0总结:

  1. 元素: 用户,角色,权限,组成权限的操作,操作对应的客体
  2. 映射: 用户-角色,角色-权限(角色与角色,角色与权限之间没有多层继承)
  3. 权限: 绑定在在计算机操作和资源客体上的抽象概念(操作 + 客体)
  4. RBAC基础模型的动态组件包括: 角色激活和主体访问
  5. 主体: 能够访问处于控制下的角色、操作和客体的活动实体(主体代表用户完成其所有请求,主体到用户应是单一映射,而用户到主体则不一定),这个概念主要出现在动态模型中

RBAC1总结:

  1. 基于rbac0,与rbac0的区别是角色之间可以多层继承
  2. 使用多层角色的原因:单一角色通常出现功能重叠的现象(属于不同角色的用户都会被授予一些一般性权限)
  3. 连接器角色:通常不直接赋予用户;可以包含任意的权限集,作为抽象功能,抽象职责,抽象任务或抽象活动(便于重用);通常如果在角色中有80%或更多的权限重叠,那么就可以选择创建一个连接器角色;

RBAC2总结:

  1. 基于rbac0,与rbac0的区别是增加约束概念(主要是职责分离约束)
  2. 职责分离(SoD): 关键操作必须由两个或更多的人来完成,这样任何一个人都不可能单独的破坏安全系统(所以在rbac中满足职责分离约束即有效角色A和有效角色B对应的用户集合不能有交集)
  3. 职责分离方法: 静态和动态方法
  4. 静态职责分离模型:在为用户指派角色时,就为角色施加约束(例如,如果为某用户授予角色A,就不能再为其授予角色B)
  5. 动态职责分离模型:用户以活动状态使用系统时其约束才会发挥作用(例如,它可以同时赋予某用户角色A和角色B,但不允许在一个会话中同时充当两个角色)

Q4.在编码实践中RBAC模块可能包含什么?

  1. 用户管理:用户的增删改查
  2. 角色管理:角色的增删改查
  3. 权限管理:权限的增删改查
  4. 日志管理:日志的增删改查
  5. 授权与撤销授权操作
  6. 资源管理:资源的增删改查(注意:这里的资源指的是那些需要被rbac模块进行权限管理的资源)
  7. 权限判断操作:提供用于判断权限的接口(常见形式如:checkAccess(user,role,params))
  8. 会话管理:即对用户在当前交互中的活动角色进行管理

Q5.身份鉴别与rbac中权限授予的区别与联系?

  1. 权限授予和身份鉴别是访问控制的基础
  2. 正确的权限授予事实上依赖于身份鉴别
  3. 身份鉴别是确定“你是谁“的过程;权限授予则是确定”你能干什么“的过程(即权限授予机制对用户是否可以访问系统资源做出”是“或”否“的决定)

Q6.在RBAC1中如何设计权限继承结构?

以下仅为个人经验

  1. 分析系统,列出一些可能存在的角色
  2. 分析系统,列出所有需要被管理的资源
  3. 对每种资源列出所有需要被管理的操作
  4. 根据每种资源的每种操作,组合出所有的基本(操作,资源)(只分析需要进行权限管理的),形成"最底层permission"
  5. 对所有当前存在的permission构成的集合进行逐层划分(按照最小权限原则,并联系可能存在的角色)
  6. 根据上一步的划分,在每一个分界处提取出角色(其中可能包含连接器角色)
  7. 整理以上的工作,得到基本权限继承结构
  8. 对基本权限继承结构中的元素进行分析,确定是否需要附加rule(rule可以用于确保是在满足一些前置条件的情况下进行权限判定,rule不一定非要附加在permission或role上,也可以附加于assignment上,看实际编码时的考虑)
  9. 将带有rule的"permission"作为其"最底层permission"的上层权限,最后如果"最底层permission"没有上层角色,则可以考虑从结构中删除
  10. 整理并回顾,优化每个元素的命名
  11. 如果在第7步中不选择在permission或role上附加rule,则需要考虑如何在assignment上附加rule

Q7.在实际项目中会经常遇到角色是基于某种资源的情况,该如何处理?

问题的具体描述:

  1. 在某一系统中,资源(客体)A需要进行权限管理。(A指的是一类资源,假设其中包括具体的该类资源a,b,c...)
  2. 存在用户u,u可以访问(access)A类资源中的a和b
  3. 用户u对于资源a被赋予角色r1,u对于资源b被赋予角色r2

需要如何实现rbac使得其满足以上需求?


Answer:

  1. 通常需要在rbac添加一个新的基本元素rule,rule的作用在于:当进行权限判定时,限定前置条件。
  2. rule可以附加在permission,role或assignment(即某个用户赋予某种角色:(user,role))中,在判定权限过程中,需要执行rule
  3. 对应于上面的问题,可以添加一张表T,T中的每条记录包含(user,resourceA,role),执行rule的目的是判断(u,a,r1)或(u,b,r2)存在于表T中
  4. 个人偏向于在assignment中绑定rule,这样可以使权限继承结构更为清晰

Q8.在实现rbac时,进行权限判定的具体逻辑是怎样的?

通常在实现的时候会用到递归,下面以YII2中提供的代码为例(源码在yii2中的位置为vendor\yiisoft\yii2\rbac\DbManager.php,这里的代码删减了一些无关的内容)

public function checkAccess($userId, $permissionName, $params = [])
{
    $assignments = $this->getAssignments($userId);//先查找当前用户的已经授予的所有角色
    if ($this->hasNoAssignments($assignments)) {
        return false;//如果没有任何授权的话,当然是判定失败
    }
    //递归
    return $this->checkAccessRecursive($userId, $permissionName, $params, $assignments);
}

protected function checkAccessRecursive($user, $itemName, $params, $assignments)
{
    if (($item = $this->getItem($itemName)) === null) {
        return false;//如果所要判定的permission或role根本不存在,自然判定失败
    }
    
    //需要判定的item存在,先执行当前Item的rule,rule可以用于执行一些业务逻辑
    if (!$this->executeRule($user, $item, $params)) {
        return false;
    }

    //如果当前需要判定的role确实授予了该用户,那么就可以返回true,结束递归
    if (isset($assignments[$itemName]) || in_array($itemName, $this->defaultRoles)) {
        return true;
    }

    //获取当前Item的上一层item,递归判定
    $query = new Query;
    $parents = $query->select(['parent'])
        ->from($this->itemChildTable)
           ->where(['child' => $itemName])
        ->column($this->db);
    foreach ($parents as $parent) {
        if ($this->checkAccessRecursive($user, $parent, $params, $assignments)) {
               return true;
        }
     }

     return false;
 }
  1. 在上面的代码中可以看到,当中使用了rule,在yii2中可以在permission或role中绑定相应的rule(但在assignment中无法绑定rule),引入rule可以解决Q7中的问题
  2. 为了实现在assignment中绑定rule,以下是经过修改后的代码(除了checkAccessRecursive方法需要修改外,还有其他的相关方法需要修改,但此处就不列出了,具体可以查看github项目:https://github.com/Darkgel/tr...)
protected function checkAccessRecursive($user, $itemName, $params, $assignments)
{
    if (($item = $this->getItem($itemName)) === null) {
        return false;
    }

    if (!$this->executeRule($user, $item, $params)) {
        return false;
    }

    if(in_array($itemName, $this->defaultRoles)){
        return true;
    }

       //这里添加了对assignment中的rule进行判断
    if (isset($assignments[$itemName])) {
        $assignment = $assignments[$itemName];
        if($this->executeRule($user, $assignment, $params)){
            return true;
        }
    }

    $query = new Query;
    $parents = $query->select(['parent'])
        ->from($this->itemChildTable)
        ->where(['child' => $itemName])
        ->column($this->db);
    foreach ($parents as $parent) {
        if ($this->checkAccessRecursive($user, $parent, $params, $assignments)) {
            return true;
        }
    }

    return false;
}

你可能感兴趣的:(php,yii2,rbac)