# 16. 安全

如何把 security 嵌入架构：threat modeling、least privilege、authn/authz、secrets、audit 与 secure defaults。

- **Author:** Fedor Chishchin
- **Level:** advanced
- **Reading time:** 约 25 分钟阅读
- **Published:** 2026-05-23
- **Source:** https://fedorthinks.com/zh/learn/software-architect-16-security

---

## 1. 核心思想

安全从一个问题开始：我们信任谁，为什么信任，以及这种信任被打破时会发生什么？

### Authn 与 authz 是两件事

> 护照证明你是谁。门票证明你有资格进场。它们不是同一份证件。

Authentication 回答的是"这是谁"。Authorization 回答的是"他被允许做什么"。常见的错误是 identity 被正确校验，却忘了检查对具体资源的访问权限。

架构师必须定义权限模型：RBAC、ABAC、ownership-based access、tenant isolation、service-to-service permissions。最关键的是，authorization 应当落在业务动作的层面，而不仅仅停留在 endpoint。

### Least privilege 缩小 blast radius

> 你家的钥匙不应该能打开整个小区。一旦被偷，损失也必须有边界。

每个 user、service、token 和 job 都应该只持有完成工作所需的最小权限。Secrets 不放在代码里。Production 访问必须受限、记录在案，并按计划复审。

Security architecture 不只评估被攻击的概率，更关注 blast radius：攻击者攻破一个组件后实际能做什么。

## 2. 例子与反例

好的安全模型让对开发者最安全的那条路同时也是最方便的那条路。

### 例子：repository 层的 tenant isolation

> 在写字楼里，每家公司都有自己的上锁的门——不是一张写着"请勿入内"的牌子。

所有数据访问都经过 repository，repository 强制从 trusted context 中获取 `tenantId`。Query builders 自动注入 tenant predicate，integration tests 保证 cross-tenant 读取不可能发生。

这比要求每个开发者手动记得加过滤器要可靠得多。

### 反例：JWT 里塞 admin flag，资源层不再校验

> 挂着"员工"工牌并不意味着可以打开金库、财务室和机房。

API 只检查 `isAdmin=true` 就放行——不验证 workspace、role scope 或资源 ownership。一个 token 给出的权限过大。一旦泄漏，损失最大化。

Authorization 必须是带上下文的：subject、action、resource、tenant、conditions。

#### 自检

- 系统中信任的边界在哪里？- 一个 service token 泄漏时会发生什么？- 资源层面的 authorization 在哪里被校验？- 哪些动作会进入 audit log？

下一模块：[可观测性](./software-architect-17-observability)。
