基本概念:主体、客体、操作、授权、鉴别、审计、安全模型

做权限系统这么多年,我见过很多团队一上来就画 ER 图、建用户表、写角色判断。结果呢?上线没两周就发现权限漏了、越权了、审计日志根本查不出是谁干的。

说白了,这些人把「权限」想简单了。权限不是一张表能解决的,它是一套完整的逻辑链条。今天我们就来拆开这套链条,看看每个环节到底是什么。

先从两个最基础的概念说起:主体与客体

你想想看,任何一次访问行为,都离不开两个角色:谁在访问?在访问什么?

  • 主体(Subject):发起动作的实体。可以是用户、进程、服务账户、API 客户端,甚至是另一个系统。我见过一个坑——有人把「用户角色」当成主体来判断权限,结果进程间调用时根本拿不到「用户」信息,直接崩溃。
  • 客体(Object):被访问的资源。文件、数据库记录、内存区域、HSM 上的密钥、硬件模块的某个接口……一切被保护的东西都是客体。

记住一句话:主体不能为空,客体必须明确。我在项目里踩过最大的坑,就是客体定义模糊。比如「所有密钥」——到底是哪个密钥?哪把密钥?谁的密钥?不明确,授权就没办法写。

操作:不只是增删改查

操作(Operation)就是主体对客体「做了什么」。常见的操作有读、写、执行、删除、导出、签名、解密……

但这里有个容易被忽略的地方:同一操作在不同客体上,含义可能完全不同。比如「写」操作,在文件系统里是修改文件内容,在 HSM 里却是导入密钥材料。我曾经给一个金融客户做 HSM 集成,他们直接把文件系统的「写」权限模型套上来,结果 HSM 的密钥写入了但无法使用——因为 HSM 的「写」还附加了安全策略校验。

我的建议:定义操作时,一定要绑定到具体客体的语义。别偷懒用通用枚举。把 HSM 的「签名」和「解密」分开定义,哪怕它们底层调的是同一个硬件接口。

授权:权限系统的核心裁决

授权(Authorization)就是回答一个问题:「这个主体能不能对这个客体做这个操作?」

授权的实现方式有很多种:ACL、RBAC、ABAC……但本质上就三步:

  1. 拿到主体信息(你是谁)
  2. 确定客体与操作(你想对什么做什么)
  3. 匹配规则(有没有策略允许你这么做)

我给你一个我在生产环境用过的决策逻辑伪代码:

function authorize(subject, object, operation):
    // 1. 获取主体所有关联的策略
    policies = getPolicies(subject)
    // 2. 过滤出跟这个客体相关的策略
    relevant = policies.filter(p => p.matches(object))
    // 3. 逐条判断
    for policy in relevant:
        if policy.allow(operation):
            return PERMIT
        if policy.deny(operation):
            return DENY
    // 4. 默认拒绝
    return DENY

看到没?默认拒绝是底线。我在设计早期版本时忘了这行,结果新用户没配置任何策略就能访问所有资源——还好是在测试环境发现的。

鉴别:你得先证明你是谁

授权的前提是鉴别(Authentication)。你连主体是谁都不知道,怎么授权?

鉴别的常见手段就那几样:

  • 你知道什么(密码、PIN码)
  • 你有什么(、智能卡、HSM 的客户端证书)
  • 你是什么(指纹、虹膜)

在 HSM 场景里,鉴别往往是双向的。不仅系统要验证调用方,调用方也要验证系统的 HSM 是不是真的。我记得有一个银行项目,攻击者伪造了一个 HSM 接口,客户端直接把密钥材料传了过去……从那以后,我所有 HSM 集成都强制加上双向 TLS + 证书固定验证。

避坑指南:不要用同一个鉴别流程去覆盖所有人。HSM 管理员和普通 API 调用者的鉴别强度要分开设计。我曾经见过管理员用弱密码登录 HSM 管理界面……嗯,当天就被我要求改了策略。

审计:出了事,你得查得出来

审计(Auditing)是最后一个环节,但也是最容易被「先上线再说」糊弄过去的。审计要记录什么?

  • 什么时间?
  • 谁(主体)?
  • 对什么(客体)?
  • 做了什么(操作)?
  • 结果如何(成功/失败)?
  • 上下文是什么(IP、会话ID、请求ID)?

我见过最糟糕的审计日志:只有「用户 X 做了操作 Y」。缺时间、缺结果、缺上下文。出事之后根本没法复盘。记住,审计日志不是给人读的,是给程序查的。所以格式要结构化,要带索引,要防篡改。

在 HSM 场景里,很多硬件设备自身就带有审计日志能力,但日志格式千奇百怪。我的习惯是:统一做一层日志标准化,把 HSM 的原生日志拉到统一格式里,然后再写查询分析。不然每次排查都要先学一遍 HSM 厂商的日志语法,太折磨了。

安全模型:把以上所有串起来

安全模型(Security Model)就是一套规则框架,告诉你主体、客体、操作、授权、鉴别、审计这些要素怎么组合、怎么约束、怎么保证安全。

主流的安全模型有这些:

模型 核心思想 典型场景 HSM 适用性
自主访问控制(DAC) 客体的所有者可以任意授权给别人 文件系统、个人数据 不推荐。HSM 密钥不能让用户随意分享
强制访问控制(MAC) 系统根据标签/等级强制决定,用户不可绕开 军事、政府、高安全系统 适合。HSM 经常需要多级密钥保护
基于角色的访问控制(RBAC) 权限绑定到角色,角色绑定到用户 企业管理、Web 应用 适合。但要注意 HSM 场景下角色粒度要够细
基于属性的访问控制(ABAC) 根据主体、客体、环境的多维属性动态决策 云平台、微服务、物联网 最适合。HSM 密钥策略经常依赖时间、IP、密钥用途等属性

我个人最推荐 ABAC 用在 HSM 集成里。为什么?因为 HSM 密钥的访问条件往往很复杂——「只有在工作时间、来自内部网络、使用特定算法时,才能用这把密钥做签名」。这种逻辑用 ABAC 写规则非常自然,用 RBAC 你得建一堆临时角色。

一张图串起所有概念

下面这张 SVG 图,我把这七个术语串在一起。你一看就明白整个流程怎么走的。

权限模型核心概念关系图 主体 (Subject) 客体 (Object) 操作 (Operation) 授权引擎 (Authorization) 匹配策略 → Permit/Deny 鉴别 (AuthN) 审计 (Audit) 安全模型 (MAC / RBAC / ABAC) 授权引擎依赖鉴别结果,触发审计日志记录,安全模型定义所有规则的边界

一个小回顾:这些概念怎么配合?

我习惯用一句话串起来:主体通过鉴别后被识别出来,请求对客体的某个操作,授权引擎根据安全模型定义的规则做出决定,同时审计系统记录全过程。

少了任何一个环节,权限系统都会出问题。没有鉴别,谁都可以冒充别人。没有客体定义,你不知道在保护什么。没有审计,出了事你连原因都查不到。

接下来我们就要进入实战了——用这些概念去设计 HSM 的权限模型。不过在那之前,我强烈建议你先用这些术语去审视一下你现在负责的系统。把主体、客体、操作列出来画一遍,你可能会发现不少漏洞。

毕竟,能把概念说清楚的人,才写得出靠谱的权限代码。