第 6 章 · 安全架构:认证鉴权与零信任
本章讲解企业级 安全纵深防御:身份认证、授权模型、网络隔离、密钥管理、常见漏洞防护与审计合规。
前置:PaaS Keycloak(ch14);网关 ch12;架构第 1 章 NFR 安全项。
6.1 安全纵深防御
互联网
│
▼
┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ WAF / DDoS │──►│ 网关鉴权 │──►│ 服务间认证 │──►│ 数据加密 │
│ 边缘过滤 │ │ JWT/OAuth │ │ mTLS / SA │ │ 传输+静态 │
└─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘
│ │ │ │
└─────────────────┴─────────────────┴─────────────────┘
审计日志(谁、何时、何种操作)
零信任原则:不信任内网位置;每次访问验证 身份 + 设备/上下文 + 策略。
| 层级 | 控制目标 | 失败假设 |
|---|
| 边缘 | 挡扫描、CC、已知漏洞利用 | WAF 可被绕过 |
| 网关 | 统一认证、粗粒度授权 | Token 泄露 |
| 服务 | 细粒度数据权限 | 网关被攻破 |
| 数据 | 加密、脱敏、最小权限账号 | 应用漏洞 SQL 注入 |
| 运维 | RBAC、审计、密钥轮换 | 内部人误操作 |
6.2 认证(Authentication)
| 方案 | 适用 | Token 生命周期 | 小紫组件 |
|---|
| Session + Cookie | 传统服务端渲染 Web | 服务端会话 TTL | Redis Session |
| JWT | 前后端分离、微服务 | Access 15min + Refresh | APISIX jwt-auth |
| OAuth2 / OIDC | 第三方登录、企业 SSO | 依 IdP | Keycloak |
| mTLS | 服务间 | 证书有效期 | cert-manager |
6.2.1 JWT 实践
// Access Token Payload(示例)
{
"sub": "U10086",
"iss": "https://auth.xiaozi.local",
"aud": "order-api",
"exp": 1734480000,
"roles": ["user"],
"scope": "orders:read orders:write"
}
| 规则 | 说明 | 反模式 |
|---|
| 短过期 | Access 15~30min | 7 天 JWT 无刷新 |
| Refresh 轮换 | 用后作废旧 refresh | refresh 永不过期 |
| 敏感操作 | 二次验证/MFA | 仅密码改手机号 |
| 算法 | RS256 / ES256 | alg=none |
| 存储 | Web:HttpOnly Cookie;移动端 Keychain | localStorage 存长期 token |
# APISIX jwt-auth 消费者(概念)
consumers:
- username: order-api
plugins:
jwt-auth:
key: order-api-key
secret: "${JWT_SECRET}" # 来自 Secret,非明文
行业案例 · 某社交平台:JWT 放 localStorage + 过期 30 天,XSS 后 批量账号接管。整改:HttpOnly Cookie + 15min access + 同源 CSP。
6.3 鉴权(Authorization)
| 模型 | 说明 | 适用 |
|---|
| RBAC | 角色 → 权限集合 | 后台管理、固定岗位 |
| ABAC | 属性(部门、职级、数据范围) | 复杂组织、行级权限 |
| ReBAC | 关系(用户-订单所有者) | 资源实例级 |
| 资源级 | 只能操作自己的订单 | C 端 API 必做 |
请求 ──► 网关:验证 JWT 有效 + scope 粗筛
──► 服务:校验 resource.ownerId == jwt.sub
──► DB:WHERE user_id = ? 参数绑定
def get_order(order_id, current_user):
order = repo.find(order_id)
if not order:
raise NotFound()
if order.user_id != current_user.id and not current_user.is_admin:
raise Forbidden() # 403,非 404(避免枚举)
return order
| 网关 vs 服务 | 网关做 | 服务必须做 |
|---|
| 认证 | 校验 JWT 签名 | 不信任未验签的内部头 |
| 粗授权 | /admin/* 需 admin 角色 | 数据行级 owner 校验 |
| 限流 | IP/用户 QPS | 业务级配额 |
6.4 网络与零信任(K8s)
| 实践 | K8s 实现 | 目标 |
|---|
| 最小暴露 | 仅 Ingress 对外;Service 默认 ClusterIP | 缩小攻击面 |
| NetworkPolicy | 限制 Pod 互访 | app 仅能连 data NS |
| 服务账号 | 每 Deployment 独立 SA | 最小 RBAC |
| 密钥 | Secret + 禁止日志打印 | 无明文 env 入 Git |
| Pod Security | restricted / 非 root | 降容器逃逸影响 |
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: order-api-ingress
namespace: app
spec:
podSelector:
matchLabels:
app: order-api
policyTypes: [Ingress, Egress]
ingress:
- from:
- namespaceSelector:
matchLabels:
name: app
- podSelector:
matchLabels:
app: apisix
ports:
- protocol: TCP
port: 8080
egress:
- to:
- namespaceSelector:
matchLabels:
name: data
ports:
- protocol: TCP
port: 3306
- to:
- namespaceSelector:
matchLabels:
name: middleware
ports:
- protocol: TCP
port: 6379
量化:生产 Namespace 100% 应有 NetworkPolicy(至少默认拒绝 + 白名单)。
6.5 密钥与合规
| 规则 | 做法 | 频率 |
|---|
| 不入 Git | .gitignore + gitleaks 扫描 | 每次 PR |
| 轮换 | DB 密码、API Key、JWT 签名密钥 | 季度 / 泄露即换 |
| 分级 | L1 公开 / L2 内部 / L3 密钥 / L4 PII | 标注数据地图 |
| 审计 | Secret 变更、管理员登录 | 留存 ≥ 180 天 |