开篇:身份是新的网络边界
在云计算和远程办公时代,传统的"网络边界"概念已经瓦解。员工可能在咖啡店、家中或机场访问企业资源,设备可能是公司配发的笔记本、个人手机或平板电脑。在这种环境下,“身份"成为了新的安全边界——你是谁、你能做什么、你在什么条件下被允许访问,这些问题比"你从哪里连接"更加重要。
身份与访问管理(IAM)是零信任架构的核心支柱。本章将覆盖现代身份协议(OAuth 2.0/OIDC/SAML)、授权模型(RBAC/ABAC/ReBAC)、特权访问管理(PAM)以及零信任身份的实施策略。
一、身份协议对比
| 协议 | 用途 | 传输 | 适用场景 | 现代推荐度 |
|---|---|---|---|---|
| OAuth 2.0 | 授权委托(Access Token) | HTTP | 第三方应用授权 | ⭐⭐⭐ 基础 |
| OpenID Connect | 身份认证(ID Token) | HTTP/JSON | SSO、用户身份验证 | ⭐⭐⭐⭐⭐ 首选 |
| SAML 2.0 | 企业 SSO | XML/SOAP | 传统企业应用 | ⭐⭐⭐ 遗留 |
| LDAP/AD | 目录服务 | TCP | 内部员工目录 | ⭐⭐⭐ 内部 |
一句话总结:新建项目首选 OIDC(基于 OAuth 2.0 的认证层),遗留企业系统使用 SAML,内部目录同步使用 LDAP/SCIM。
二、OAuth 2.0 + OIDC 实战
2.1 授权流程
┌──────────┐ ┌──────────┐
│ Client │──(1) Authorization Request + PKCE──►│ Auth │
│ (App) │◄─(2) Authorization Code + State────│ Server │
├──────────┤ ├──────────┤
│ Client │──(3) Token Request (Code + Verifier)►│ Auth │
│ (App) │◄─(4) Access Token + ID Token + Refresh──│ Server │
└──────────┘ └──────────┘
│
▼ (5) API Request with Bearer Token
┌──────────┐
│ Resource │
│ Server │
└──────────┘
PKCE(Proof Key for Code Exchange):防止授权码拦截攻击
State:防止 CSRF 攻击
2.2 JWT Token 结构
Header:
{
"alg": "ES256", // EdDSA 或 ECDSA 优于 RSA
"typ": "JWT",
"kid": "2024-01" // Key ID 用于密钥轮换
}
Payload:
{
"iss": "https://auth.example.com", // 签发者
"sub": "user_12345", // 用户标识
"aud": "api.example.com", // 受众
"exp": 1704067200, // 过期时间(短时效)
"iat": 1704063600, // 签发时间
"jti": "unique-token-id", // 唯一标识(用于撤销)
"scope": "read:profile write:posts", // 权限范围
"roles": ["user", "premium"] // 角色声明
}
Signature:
ECDSA-SHA256(base64url(header) + "." + base64url(payload), private_key)
2.3 Token 安全最佳实践
# Access Token:短时效(5-15 分钟),无状态
# Refresh Token:长时效,存储在 HttpOnly Cookie 或安全存储
# Token 验证中间件(Python/FastAPI)
from jose import jwt, JWTError
from fastapi import HTTPException, Depends
from fastapi.security import HTTPBearer
security = HTTPBearer()
async def verify_token(credentials: HTTPBearer = Depends(security)):
token = credentials.credentials
try:
payload = jwt.decode(
token,
key=PUBLIC_KEY,
algorithms=["ES256"],
audience="api.example.com",
issuer="https://auth.example.com",
)
# 检查 Token 是否在撤销列表(Redis)
jti = payload.get("jti")
if await redis.exists(f"revoked:{jti}"):
raise HTTPException(status_code=401, detail="Token revoked")
return payload
except JWTError:
raise HTTPException(status_code=401, detail="Invalid token")
一句话总结:OIDC 是现代身份认证的基石——短时效 Access Token 用于 API 访问,长时效 Refresh Token 用于会话维持,JWT 撤销列表用于紧急下线。
三、授权模型进化
3.1 RBAC(基于角色的访问控制)
# RBAC 模型
roles:
admin:
permissions:
- user:*
- post:*
- setting:*
editor:
permissions:
- post:read
- post:write
- post:publish
viewer:
permissions:
- post:read
# 用户-角色映射
user_roles:
alice: [admin]
bob: [editor]
carol: [viewer]
3.2 ABAC(基于属性的访问控制)
# ABAC 策略引擎
class ABACEngine:
def evaluate(self, subject, resource, action, environment):
"""
subject: { user, roles, department, clearance }
resource: { owner, classification, department }
action: read | write | delete
environment: { time, location, device_trust }
"""
policy = {
"allow": [
# 规则 1:数据所有者可以读写自己的数据
{
"subject.user": resource.owner,
"action": ["read", "write"],
},
# 规则 2:同部门成员在工作时间可以读取
{
"subject.department": resource.department,
"resource.classification": "internal",
"action": "read",
"environment.time": {"between": ["09:00", "18:00"]},
},
# 规则 3:高管可以访问高密级数据
{
"subject.clearance": {"gte": resource.classification},
"action": "read",
},
],
"deny": [
# 拒绝规则覆盖允许规则
{
"environment.device_trust": {"lt": 0.5},
},
]
}
# 先评估 deny 规则
for rule in policy["deny"]:
if self.match(rule, subject, resource, action, environment):
return False
# 再评估 allow 规则
for rule in policy["allow"]:
if self.match(rule, subject, resource, action, environment):
return True
return False # 默认拒绝
3.3 ReBAC(基于关系的访问控制)
# Google Zanzibar 风格的 ReBAC
# 关系如:document:readme#owner@user:alice
relations = {
"document:readme": {
"owner": ["user:alice"],
"editor": ["user:bob", "group:engineering#member"],
"viewer": ["group:company#member"],
}
}
# 检查权限:alice 是否是 readme 的 owner?
check("document:readme", "owner", "user:alice") # ✅ True
# 检查权限:bob 是否可以 viewer readme?(viewer ⊆ editor ⊆ owner)
check("document:readme", "viewer", "user:bob") # ✅ True(继承 editor)
一句话总结:授权模型从 RBAC 的"角色标签"进化到 ABAC 的"动态属性判断”,再到 ReBAC 的"关系图遍历"——复杂场景选 ABAC/ReBAC,简单场景 RBAC 足够。
四、零信任身份实施
4.1 核心原则
| 原则 | 实施方式 |
|---|---|
| 永不信任,始终验证 | 每次访问都验证身份和设备状态 |
| 最小权限 | 只授予完成任务所需的最低权限 |
| 假设失陷 | 内网流量同样加密和监控 |
| 动态授权 | 基于实时风险评估调整权限 |
4.2 设备信任评分
class DeviceTrustScore:
def calculate(self, device) -> float:
score = 1.0
# 设备合规性检查
if not device.encrypted:
score *= 0.3
if not device.os_updated:
score *= 0.5
if device.jailbroken:
score *= 0.0 # 完全不可信
# 位置检查
if device.location not in self.allowed_countries:
score *= 0.4
# 行为分析
if device.anomaly_score > 0.8:
score *= 0.3
return score
# 动态访问决策
if device_trust < 0.5:
require_step_up_auth() # 要求额外认证
elif device_trust < 0.3:
deny_access() # 拒绝访问
else:
allow_access() # 正常访问
一句话总结:零信任不是"不信任任何人",而是"验证每个人、每件事、每次访问"——身份验证只是起点,设备状态、行为分析和动态授权才是完整的零信任闭环。
FAQ
Q1: OAuth 2.0 和 OIDC 有什么区别?
OAuth 2.0 是授权框架(“你能做什么”),OIDC 是认证层(“你是谁”)。OIDC 在 OAuth 2.0 基础上增加了 ID Token(JWT 格式的用户身份信息)。
Q2: JWT 撤销的的性能问题怎么解决?
- 短时效 Access Token(5-15 分钟),撤销只在 Refresh Token 层面生效
- 使用 Redis 等内存数据库存储撤销列表(JTI)
- 区域缓存:在网关层缓存撤销列表,减少中心查询
Q3: RBAC 和 ABAC 可以共存吗?
可以。常见模式:RBAC 处理粗粒度权限(页面/API 级别),ABAC 处理细粒度数据权限(字段/行级别)。
Q4: 如何选择 IDP(身份提供商)?
| 场景 | 推荐 |
|---|---|
| 纯内部员工 | Okta / Azure AD / 企业微信 |
| 面向消费者的应用 | Auth0 / Firebase Auth / Keycloak |
| 混合场景 | Keycloak(自托管)/ Authentik |
| 开发者/开源 | Keycloak / Authelia |
相关阅读
- https://plumephp.com/security-zero-trust-architecture/ — 零信任网络安全架构
- https://plumephp.com/security-authentication-session/ — 身份认证与会话安全
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。