访问控制基础概念:主体、客体、操作、权限、安全标签、信任边界

做权限系统,绕不开六个核心概念。我刚开始接触访问控制时,以为就是「谁能不能干什么」这么简单。后来被现实狠狠教育了几次,才发现这六个概念之间环环相扣,漏掉一个,整个模型就可能崩掉。

这一章我把它们拆开讲清楚。每个概念我都会结合真实的踩坑经历,希望能帮你少走弯路。

主体:谁在发起访问

主体就是主动发起访问请求的实体。说白了,就是那个「想要干点啥」的角色。

主体的范围比你想象的要宽:

  • 自然人用户:像你我这样的真实账号
  • 服务账户:后台进程、微服务之间的调用身份
  • 设备/终端:IoT 传感器、运维堡垒机
  • API :无状态的调用方身份

我在项目中遇到过一个问题:有人把 Service Account 和自然人主体混在同一个权限体系里管理。结果离职流程只清理了人工账号,那些服务账户的密钥却一直遗留在生产环境。嗯,后来出了一次数据泄露,查根因才发现是这个问题。我个人习惯是:在模型设计阶段就把主体类型分清楚,自然人、服务、设备分别用不同的标识前缀,审计时就能快速定位。

避坑:我曾经在金融项目里看到过一张权限表,subject_id 字段同时存了用户名、IP 地址和进程 PID。查询时根本分不清谁是谁。审计日志一塌糊涂。主体必须有明确的类型标签,别偷懒。

客体:被保护的对象

客体就是主体想要访问的资源。可以是一张数据库表、一个文件、一台服务器,甚至是一个内存对象。

客体常见的分类方式:

  • 数据层:表、行、列、字段
  • 服务层:API 端点、消息队列、RPC 接口
  • 基础设施层:服务器、容器、网络策略
  • 应用层:菜单、按钮、页面路由

我印象很深的一次:某个团队把数据库表的权限粒度只做到了「表级别」,结果普通员工能看到整个用户表的手机号。原因就是客体分类不够细,没有把「列」作为独立的客体粒度来建模。后来他们改成了列级别的权限控制,才把敏感字段隔离开。

设计建议:客体的粒度直接决定了权限模型的精细度。你想想看,如果客体只粗到「数据库」这个级别,那就只有「能进/不能进」两种结果,跟没有权限控制区别不大。

操作:访问的动作

操作就是主体对客体执行的具体动作。最经典的当然是 CRUD——创建、读取、更新、删除。但在真实业务里,操作远不止这四种。

常见操作类型:

  • 数据操作:SELECT、INSERT、UPDATE、DELETE、EXPORT、IMPORT
  • 管理操作:CREATE_TABLE、ALTER_SCHEMA、GRANT、REVOKE
  • 流程操作:APPROVE、REJECT、TRANSFER、CLOSE
  • 特殊操作:MASK(脱敏)、ENCRYPT、DECRYPT、AUDIT

我见过最糟的案例是,某系统把所有操作粗粒度地定义为「读写」两种。结果一个只读账号居然能通过某个 API 触发数据导出。为什么?因为那个 API 内部调用了存储过程,而存储过程被归到了「读」操作里。这就是操作粒度太粗导致的权限逃逸。

核心原则:操作的定义要跟实际执行的动作一一对应,别用「读写」这种模糊分类去覆盖所有场景。

权限:访问的许可

权限是把主体、客体、操作三者绑定在一起的决策结果。它回答的是:「谁能在哪个资源上做什么事」。

权限的表现形式通常是:

  • 允许/拒绝:二元决策,最简单也最常用
  • 条件许可:加上时间、IP、设备状态等上下文
  • 带义务的许可:比如「允许导出,但必须同时记录审计日志」

我之前带团队时犯过一个错:权限继承层级搞了七层——公司 → 部门 → 团队 → 项目 → 环境 → 应用 → 功能。结果排查一个用户为什么能访问某个数据时,要沿着继承链查七层,每一层还有可能被拒绝策略覆盖。排查一次至少半小时。后来我学乖了:继承层级不超过三层,超出就用显式授权。

权限类型 特点 适用场景 风险等级
直接授权 显式绑定,无歧义 核心数据、敏感操作 低
角色继承 便于批量管理 常规业务、非敏感资源 中
动态推导 基于属性实时计算 大数据量、千人千面场景 高(需审计补偿)
避坑:我曾经在生产环境上直接用 UPDATE 语句修改权限表里的 effect 字段,从 deny 改成 allow。结果忘了刷新缓存,权限没生效,线上事故持续了 40 分钟。权限变更必须有原子化提交 + 缓存强制失效流程,别手贱直接改数据库。

安全标签:安全属性标记

安全标签是强制访问控制(MAC)里的核心概念。它给主体和客体都打上安全属性标记,然后由系统根据预定义的规则判断是否能访问。

典型的安全标签体系:

  • 机密级:绝密、机密、秘密、公开
  • 类别级:财务、人事、研发、运维
  • 合规级:PCI、GDPR、HIPAA、等保

我在做政府项目时被安全标签折腾过。当时的需求是:标记为「机密」的数据,只能被安全级别大于等于「机密」的主体访问,而且主体必须有相应的类别授权。这个规则听起来简单,但在实现时发现——标签本身也需要防篡改。如果标签存储在客户端,攻击者可以伪造。所以安全标签必须由可信的授权中心签发,并在每次鉴权时校验签名。

设计建议:安全标签不是数据库里的一个普通字段。它是鉴权决策的输入参数,必须由系统强制绑定,不能让用户自己修改。否则标签就失去了「强制」的意义。

信任边界:安全域的分界线

信任边界是不同信任等级之间的分界线。边界内部的实体被认为是可信的,边界外部的实体则需要额外的验证。

理解信任边界的关键:

  • 边界不是物理的:它可以是网络隔离、进程隔离、甚至是数据隔离
  • 信任是相对的:内网不等于可信,零信任模型下所有流量都要验证
  • 边界是动态的:微服务架构里,服务之间的信任边界随着部署环境变化

我在设计微服务架构时对信任边界的理解吃过一次亏。当时我们把所有服务放在同一个 Kubernetes 集群里,认为集群内部是可信的,服务间调用不鉴权。结果一个边缘服务被攻破后,攻击者直接通过内部 API 调用了核心支付服务。那次事故之后,我们才真正落实了服务间的 mTLS 和细粒度鉴权。

核心原则:信任边界必须显式定义。不要默认「内网就安全」。你想想看,现代架构里攻击者一旦进入内网,横向移动的速度比你想象的要快得多。

概念关系图谱

下面这张图把这六个概念的关系画在了一起。中心是访问控制决策,六个概念分别从不同维度参与决策。我建议你先看整体结构,再回忆每个概念的细节。

访问控制六大概念关系图 访问控制核心 Access Control 主体 Subject 发起访问的实体 客体 Object 被访问的资源 操作 Operation 执行的动作 权限 Permission 访问的许可 安全标签 Security Label 信任边界 Trust Boundary 请求访问 执行操作 授权决策 标记等级 划定范围

实践中的组合应用

这六个概念不是孤立存在的。在真实的权限系统里,它们会组合成一条完整的决策链。我拿一个常见的 SQL 审计场景举例:

假设我们要记录「谁在什么时间查询了订单表的手机号字段」。

这条审计日志里就包含了全部六个概念:

  • 主体:user_id = 'zhangsan'
  • 客体:table = 'orders', column = 'phone'
  • 操作:SELECT
  • 权限:granted(经 RBAC 角色判定)
  • 安全标签:敏感等级 = 'PII'
  • 信任边界:来源 IP = 内网段,session 来自可信网关

对应的权限表结构可以这样设计:

CREATE TABLE access_policies (
    policy_id       INT PRIMARY KEY AUTO_INCREMENT,
    subject_type    VARCHAR(16)  NOT NULL,   -- user / service / device
    subject_id      VARCHAR(64)  NOT NULL,
    object_type     VARCHAR(16)  NOT NULL,   -- table / column / api
    object_id       VARCHAR(128) NOT NULL,
    operation       VARCHAR(32)  NOT NULL,   -- SELECT / INSERT / EXPORT
    security_label  VARCHAR(16)  DEFAULT NULL, -- public / internal / confidential
    trust_boundary  VARCHAR(32)  DEFAULT NULL, -- internal / dmz / external
    effect          ENUM('allow','deny') NOT NULL,
    created_at      DATETIME     NOT NULL,
    expire_at       DATETIME     DEFAULT NULL,
    INDEX idx_subject (subject_type, subject_id),
    INDEX idx_object (object_type, object_id)
);
个人习惯:我在设计权限表时,一定会把 security_label 和 trust_boundary 单独列出来,而不是放在一个通用的 attributes JSON 字段里。为什么?因为审计查询时,这两个字段是高频过滤条件。放在 JSON 里查询性能会很差,而且没法建索引。
本章要点:主体、客体、操作、权限、安全标签、信任边界,这六个概念共同构成了访问控制的完整语义。任何一个概念缺失,都会导致权限模型出现漏洞或盲区。你在设计系统时,可以拿这六个维度逐个检查你的权限策略,看看有没有遗漏。