访问控制模型:RBAC基于角色的访问控制和ABAC基于属性的访问控制

25 阅读12分钟

诸神缄默不语-个人技术博文与视频目录

想象一下,你管理着一栋有上百个房间的智能大厦——如何确保每个人只能进入自己该进的房间?

引言:无处不在的“门禁系统”

每天早上上班,你用员工卡刷开公司玻璃门;登录办公系统时,系统自动展示你能访问的模块;查看公司文件时,有些文档你能编辑,有些只能阅读——这些场景背后都隐藏着一套精密的访问控制系统

今天我们来聊聊两种主流的权限管理模型:RBAC(基于角色的访问控制)ABAC(基于属性的访问控制)。它们就像管理大厦的两种不同思路,各有千秋。

第一部分:RBAC——按“职位”发钥匙的智慧

什么是RBAC?

RBAC(Role-Based Access Control)的核心思想很简单:根据用户的角色分配权限

就像在一家公司里:

  • 所有“财务人员”都能访问财务系统

  • 所有“项目经理”都能查看项目进度

  • 所有“实习生”的权限都很有限

你不需要为每个员工单独设置权限,只需要定义好角色,然后把角色分配给员工。

RBAC的三层结构

让我们用中小学综合管理系统的例子来理解RBAC:

想象一所拥有 2000名学生、150名教师和30名行政人员 的学校,需要管理教学系统、财务系统、宿舍系统等多个平台。

RBAC 的核心三要素:

1. 用户系统的独立使用者

  • 学生:张三(高一1班)、李四(高二3班)...等2000人

  • 教师:王老师(语文组)、赵老师(数学组/班主任)...等150人

  • 行政人员:孙会计(财务处)、周主任(教务处)、吴校长...等30人

2. 角色权限的集合,连接用户与权限的“职位标签”

  • 学生角色:查看个人课表、提交作业、查看成绩

  • 教师角色:发布作业、录入成绩、查看所教班级课表

  • 班主任角色:管理班级信息、批准学生请假、查看本班所有学生成绩

  • 财务角色:收取学费、发放工资、查看财务报表

  • 校长角色:查看全校数据、审批预算、发布校级通知

3. 权限系统内的具体操作能力

  • 权限1:成绩.查看.本人

  • 权限2:成绩.录入.所授课程

  • 权限3:财务.收费.学费

  • 权限4:通知.发布.全校

RBAC如何优雅处理大规模用户?

情景A:新生入学

  • 传统方式(无RBAC):系统管理员需要为500名新生逐个手动设置:允许看课表、允许提交作业、不允许看他人成绩...

  • RBAC方式:管理员只需做两步:

    1. 将500名新生批量选中,分配 “学生角色”

    2. 系统自动赋予该角色下的所有权限(查看个人课表、提交作业等)

情景B:权限变更

学校规定“班主任可查看本班所有学生联系方式”:

  • 传统方式:找到全校40位班主任,逐个添加新权限。

  • RBAC方式:只需在后台修改一次 “班主任角色”,添加联系信息.查看.本班权限,所有班主任自动获得。

情景C:角色继承(高级RBAC特性)

  • “班主任角色”继承“教师角色”的所有权限(自动拥有发布作业、录入成绩等能力)

  • “年级组长角色”继承“班主任角色”的所有权限,并额外增加“查看本年级报表”权限

  • 这种继承关系形成了清晰的权限层级树,管理效率极高。

为什么角色和用户要分开?—— 应对人员变动

  1. 赵老师从普通教师晋升为班主任

    • 操作:在赵老师的账户上,将角色从“教师”变更为“班主任”

    • 结果:她自动失去了与班主任职责无关的某些权限,自动获得了班级管理、查看全班成绩等新权限。

  2. 孙会计离职,新招聘了郑会计

    • 操作:将孙会计的“财务角色”移除,给郑会计添加“财务角色”

    • 结果:权限交接安全、完整、一键完成,无需担心遗漏或误留权限。

RBAC的真正威力所在

RBAC在大规模、结构化组织中的核心优势

  • 批量操作:一次性管理成千上万用户的权限

  • 稳定性:即使人员频繁变动,只要组织架构(角色定义)稳定,系统权限就稳定

  • 可审计性:很容易回答“谁有这个权限?”(查角色)和“这个人有什么权限?”(查用户所属角色)

  • 最小特权原则:每个角色只拥有完成工作所必需的权限,降低风险

对比思考:如果这个学校用ABAC会怎样?

对于“允许学生查看自己的成绩”这条规则:

  • RBAC:所有“学生角色”都有成绩.查看.本人权限(简单直接)

  • ABAC:策略可能是:允许 如果 用户.类型=="学生" 且 资源.所有者ID == 用户.ID(更动态,但需维护用户和资源的属性)

关键区别:RBAC关注“你是什么职位”,ABAC关注“你是谁、要看什么、在什么情况下”。

RBAC的优点:简单直观

  1. 易于管理:公司新来10个财务人员?给他们分配“财务角色”即可

  2. 降低错误:权限变更时只需修改角色,无需逐个修改用户

  1. 符合直觉:与现实中的职位体系高度对应

RBAC的局限性:不够灵活

想象这个场景:公司有一份“高管级别才能查看的财务报表”。在RBAC中,你需要:

  1. 创建“高管”角色

  2. 将权限分配给该角色

  3. 将每位高管加入这个角色

但如果权限规则更复杂呢?比如:

  • “工作5年以上的项目经理可以查看高级项目数据”

  • “仅当项目属于自己部门且不在保密期内时才可访问”

这时,单纯依靠角色就不够用了。

第二部分:ABAC——智能动态的“安检系统”

什么是ABAC?

ABAC(Attribute-Based Access Control)采用更精细的思路:根据各种属性动态决定访问权限

属性可以包括:

  • 用户属性(部门、职级、工龄)

  • 资源属性(文档密级、所属部门、创建时间)

  • 环境属性(当前时间、访问地点、设备类型)

  • 操作属性(读取、编辑、删除)

ABAC的工作方式:四个维度的“安检”

想象一个高级研发中心的门禁系统:

访问请求:“张三想查看‘未来项目’文档”

ABAC系统会检查

  1. 用户属性:张三是“研发部”的“高级工程师”吗?

  2. 资源属性:“未来项目”文档的“密级”是多少?属于哪个部门?

  3. 环境属性:现在是工作时间吗?张三是从公司内网访问吗?

  4. 操作属性:张三是想“查看”还是“编辑”?

系统根据预设策略做出决定:

IF 用户.部门 == 资源.所属部门 
   AND 用户.安全级别 >= 资源.密级
   AND 环境.时间在“工作日9:00-18:00”
   AND 环境.IP地址在公司网段内
THEN 允许访问
ELSE 拒绝访问

ABAC的强大之处

  1. 极度精细:可以定义非常具体的条件

  2. 动态适应:权限可以随环境变化自动调整

  3. 集中管理:所有策略在一个地方定义和维护

ABAC的复杂性代价

不过,ABAC也有代价:

  • 策略可能很复杂:像编程一样编写策略规则

  • 管理成本高:需要维护各种属性数据

  • 性能考虑:每次访问都需要评估多个属性

第三部分:RBAC vs ABAC——如何选择?

直观对比

维度RBACABAC
核心思想角色是权限的桥梁属性决定访问权限
管理方式管理用户-角色关系管理策略和属性
灵活性相对固定高度灵活
复杂度简单直观相对复杂
适用场景组织结构稳定、权限需求简单需求复杂、需要精细控制

选择指南:像选工具一样思考

选择RBAC当

  • 你的组织结构稳定,角色定义清晰

  • 权限需求相对简单固定

  • 你希望系统简单易懂,易于维护

  • 团队技术能力有限,需要快速上手

选择ABAC当

  • 你需要精细到行/字段级别的权限控制

  • 权限规则复杂,依赖多种条件

  • 你需要动态权限,随时间、地点等变化

  • 你愿意投入资源维护属性系统和策略

现实中的混合使用

在实际应用中,很多系统采用混合模式

  • 用RBAC处理大部分常规权限

  • 用ABAC处理特殊、复杂的权限需求

比如银行系统:

  • 普通操作员权限用RBAC管理(柜员、主管等角色)

  • 高风险交易用ABAC控制(考虑金额、时间、地点、用户行为评分等多种属性)

第四部分:技术实现一瞥

RBAC的典型数据库设计

-- 简化的RBAC表结构
用户表 (id, 姓名, ...)
角色表 (id, 角色名, ...)
权限表 (id, 权限名, ...)
用户_角色表 (用户id, 角色id)
角色_权限表 (角色id, 权限id)

ABAC的策略示例(XACML)

XACML(可扩展访问控制标记语言)总之是一套用来管理授权的协议,通常用于实现ABAC策略。

通过基于JSON/XML格式的语言来描述授权规则、访问需求。

sequenceDiagram
    participant User as 用户 (张三)
    participant PEP
    participant PDP
    participant PIP as PIP (属性源)
    participant PAP as PAP (策略库)

    User->>PEP: 尝试编辑文档
    PEP->>PDP: 构造并发送XACML请求<br>(谁,对什么,做什么,何时)
    PDP->>PAP: 查询相关策略
    PAP-->>PDP: 返回策略 (Policy_ProjectDoc_Edit)
    PDP->>PIP: 获取可能缺失的动态属性
    PIP-->>PDP: 返回属性值
    Note over PDP: 评估:请求属性 vs 策略条件
    PDP-->>PEP: 返回XACML响应 (Permit/Deny)
    PEP->>User: 执行决策<br>(允许访问或拒绝)

一个示例场景的规则是:“允许项目经理在工作时间(09:00-17:00)编辑其负责的项目文档。”

这个规则涉及了ABAC的所有要素:用户属性(角色、负责项目)、资源属性(类型、所属项目)、动作(编辑)和环境属性(当前时间)。

第一部分:访问请求 (Access Request)

当用户 张三 在某个工作日的 10:30 试图编辑一份名为 “凤凰计划概要.docx” 的文档时,嵌入在文档管理系统中的 PEP 会拦截此操作,并构造一个如下格式的XACML标准请求(通常为XML,现代实现也支持JSON),发送给 PDP:

<Request xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" CombinedDecision="false" ReturnPolicyIdList="false">
  <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">edit</AttributeValue>
    </Attribute>
  </Attributes>
  <Attributes Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:subject:subject-id" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">zhangsan</AttributeValue>
    </Attribute>
    <Attribute AttributeId="role" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">project_manager</AttributeValue>
    </Attribute>
    <Attribute AttributeId="managedProject" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">project_phoenix</AttributeValue>
    </Attribute>
  </Attributes>
  <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource">
    <Attribute AttributeId="urn:oasis:names:tc:xacml:1.0:resource:resource-id" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">/docs/phoenix/overview.docx</AttributeValue>
    </Attribute>
    <Attribute AttributeId="documentType" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">project_document</AttributeValue>
    </Attribute>
    <Attribute AttributeId="belongsToProject" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">project_phoenix</AttributeValue>
    </Attribute>
  </Attributes>
  <Attributes Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment">
    <Attribute AttributeId="current_time" IncludeInResult="false">
      <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">10:30:00</AttributeValue>
    </Attribute>
  </Attributes>
</Request>

关键信息提取:

  • 谁 (Subject): zhangsan,角色 project_manager,负责项目 project_phoenix

  • 对什么 (Resource): 文件 /docs/phoenix/overview.docx,类型 project_document,所属项目 project_phoenix

  • 做什么 (Action): edit

  • 在何时 (Environment): 10:30:00

第二部分:授权策略 (Policy)

PDP 收到请求后,会从 PAP 存储的策略库中查找相关策略。以下是匹配上述请求的一条XACML策略。

<Policy xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17" PolicyId="Policy_ProjectDoc_Edit" RuleCombiningAlgId="urn:oasis:names:tc:xacml:1.0:rule-combining-algorithm:first-applicable" Version="1.0">
  <Description>允许项目经理在工作时间编辑其负责的项目文档</Description>
  <Target> <!-- 此策略适用于的目标:当操作是“edit”且资源类型是“project_document”时 -->
    <AnyOf>
      <AllOf>
        <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
          <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">edit</AttributeValue>
          <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:action" AttributeId="urn:oasis:names:tc:xacml:1.0:action:action-id" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
        </Match>
      </AllOf>
    </AnyOf>
    <AnyOf>
      <AllOf>
        <Match MatchId="urn:oasis:names:tc:xacml:1.0:function:string-equal">
          <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">project_document</AttributeValue>
          <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="documentType" DataType="http://www.w3.org/2001/XMLSchema#string" MustBePresent="true"/>
        </Match>
      </AllOf>
    </AnyOf>
  </Target>

  <Rule Effect="Permit" RuleId="Rule_Permit_Edit_In_Hours"> <!-- 核心规则:允许 -->
    <Description>项目经理可在工作时间编辑其项目文档</Description>
    <Target/> <!-- 此规则继承Policy的Target -->
    <Condition> <!-- 具体的逻辑条件 -->
      <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and">
        <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> <!-- 检查用户角色 -->
          <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
            <AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="role" DataType="http://www.w3.org/2001/XMLSchema#string"/>
          </Apply>
          <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#string">project_manager</AttributeValue>
        </Apply>
        <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-equal"> <!-- 检查项目匹配 -->
          <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
            <AttributeDesignator Category="urn:oasis:names:tc:xacml:1.0:subject-category:access-subject" AttributeId="managedProject" DataType="http://www.w3.org/2001/XMLSchema#string"/>
          </Apply>
          <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:string-one-and-only">
            <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:resource" AttributeId="belongsToProject" DataType="http://www.w3.org/2001/XMLSchema#string"/>
          </Apply>
        </Apply>
        <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:and"> <!-- 检查时间范围 -->
          <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-greater-than-or-equal">
            <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only">
              <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" AttributeId="current_time" DataType="http://www.w3.org/2001/XMLSchema#time"/>
            </Apply>
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">09:00:00</AttributeValue>
          </Apply>
          <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-less-than-or-equal">
            <Apply FunctionId="urn:oasis:names:tc:xacml:1.0:function:time-one-and-only">
              <AttributeDesignator Category="urn:oasis:names:tc:xacml:3.0:attribute-category:environment" AttributeId="current_time" DataType="http://www.w3.org/2001/XMLSchema#time"/>
            </Apply>
            <AttributeValue DataType="http://www.w3.org/2001/XMLSchema#time">17:00:00</AttributeValue>
          </Apply>
        </Apply>
      </Apply>
    </Condition>
  </Rule>

  <Rule Effect="Deny" RuleId="Rule_Deny_Default"/> <!-- 默认规则:拒绝一切不符合Permit规则的请求 -->
</Policy>

策略逻辑解读:

  1. 目标 (Target):该策略只针对 action-ideditdocumentTypeproject_document 的请求。

  2. 规则 (Rule)

    • Permit规则:在满足所有三个条件时生效:(1)用户角色是project_manager,(2)用户负责的项目(managedProject)等于文档所属项目(belongsToProject),(3)当前时间在 09:0017:00 之间。

    • Deny规则:如果所有 Permit 规则都不适用,则默认拒绝。

第三部分:决策响应 (Response)

PDP 收到请求,并评估相关策略(本例中即上述策略)后,会生成一个标准的XACML响应,发回给 PEP

<Response xmlns="urn:oasis:names:tc:xacml:3.0:core:schema:wd-17">
  <Result>
    <Decision>Permit</Decision> <!-- 核心决策:允许 -->
    <Status>
      <StatusCode Value="urn:oasis:names:tc:xacml:1.0:status:ok"/>
    </Status>
    <!-- 可选:PDP可以返回它依据了哪些策略和规则 -->
    <PolicyIdentifierList>
      <PolicyIdReference Version="1.0">Policy_ProjectDoc_Edit</PolicyIdReference>
    </PolicyIdentifierList>
    <AssociatedAdvice/> <!-- 可选的建议信息 -->
  </Result>
</Response>

PEP 收到这个包含 <Decision>Permit</Decision> 的响应后,便允许用户 张三 执行此次编辑操作。

以上三个部分构成了一个完整的逻辑闭环。

企业级价值体现在:

当公司需要修改规则时(例如,将“工作时间”改为“7x24小时”,或增加“仅限内网”的条件),管理员只需在PAP中修改并发布这一条XACML策略。之后,所有集成了PEP的文档管理、代码仓库、CRM等系统,在遇到同类请求时,都会自动遵循新规则,实现了权限的集中、动态、一致的管理。

结语:权限管理的本质思考

无论是RBAC还是ABAC,核心都是在安全便利之间寻找平衡。好的权限系统应该像一位明智的管家:

  • 知道何时严格(保护敏感数据)

  • 知道何时灵活(促进协作效率)

  • 能够适应变化(随组织发展而演进)

在数字世界中,权限管理不仅是技术问题,更是组织管理哲学的体现。理解RBAC和ABAC的差异,能帮助我们在设计系统时做出更明智的选择。


最后的小测试:想一想你每天使用的系统——公司的OA、云盘、项目管理工具。它们使用的是RBAC还是ABAC?你能找到线索吗?

掌握权限管理的艺术,就是掌握数字世界秩序的钥匙。

image.png