第三章 认证与授权机制:API Key、OAuth2、JWT 令牌、签名算法
Agent 接口的安全基石在于认证(Authentication)与授权(Authorization)。本章剖析四种主流机制:API Key、OAuth2、JWT 令牌和签名算法。每种方案适用于不同的安全等级与交互场景,开发者需根据 Agent 暴露范围、调用频率、敏感程度选择组合。
核心目标:理解令牌生命周期、签名防篡改原理、授权码流程,并能独立完成服务端与客户端的认证对接。
3.1 API Key
最简单的静态令牌方案,适合内部服务或低风险调用。客户端在 HTTP Header 或 URL Query 中携带 X-API-Key。
| 特性 | 说明 |
|---|---|
| 存储 | 服务端加密存储(bcrypt/scrypt),避免明文泄露 |
| 传输 | 仅 HTTPS,防止中间人嗅探 |
| 轮换 | 提供 /v1/keys/rotate 接口,旧 Key 设置宽限期 |
| 风险 | 密钥泄露后无法撤销单个会话,需配合 IP 白名单 |
# 客户端请求示例
GET /api/v1/agent/action
Host: agent.example.com
X-API-Key: sk_prod_abc123xyz
Content-Type: application/json
最佳实践:API Key 仅作为身份标识,不包含权限信息;权限通过服务端角色绑定。建议使用 UUIDv4 或 nanoID 生成不可猜测的 Key。
3.2 OAuth2 授权码流程
OAuth2 用于第三方应用代表用户访问 Agent 资源。核心流程:授权码(Authorization Code) → 访问令牌(Access Token) → 刷新令牌(Refresh Token)。
// 授权请求(302 重定向)
GET /authorize?response_type=code
&client_id=agent_web
&redirect_uri=https://app.example.com/callback
&scope=agent:execute agent:read
&state=nonce_random
// 令牌交换(后端发起)
POST /token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=8xJO0m4p...
&redirect_uri=https://app.example.com/callback
&client_id=agent_web
&client_secret=sec_xxx
// 响应
{
"access_token": "eyJhbGciOi...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "def50200..."
}
安全注意:授权码必须一次性使用,且验证
state 参数防止 CSRF;刷新令牌应支持 Rotation(每次刷新返回新令牌)。
3.3 JWT(JSON Web Token)
自包含的令牌结构:Header.Payload.Signature。Agent 服务端无需查询数据库即可校验身份和权限。
// JWT 载荷示例(解码后)
{
"sub": "user_agent_01",
"iss": "https://auth.example.com",
"aud": "agent_platform",
"iat": 1718000000,
"exp": 1718003600,
"scope": "agent:execute",
"session_id": "sess_abc"
}
推荐算法:RS256(非对称)或 HS256(对称)。对称签名适合单一可信节点,非对称适合分布式微服务。
// Node.js 签发与验证示例(jsonwebtoken 库)
const jwt = require('jsonwebtoken');
const privateKey = fs.readFileSync('private.pem');
const token = jwt.sign({ scope: 'agent:execute' }, privateKey, {
algorithm: 'RS256', expiresIn: '1h', issuer: 'agent_auth'
});
// 验证
try {
const payload = jwt.verify(token, publicKey, { algorithms: ['RS256'] });
// payload 包含 scope、exp 等
} catch (e) {
// 过期或签名错误 -> 拒绝
}
3.4 签名算法
无论是 API Key、JWT 还是 OAuth2 Client Secret,底层都需要签名算法防止篡改。常见四类:
| 算法 | 类型 | 典型用途 | 签名长度 |
|---|---|---|---|
| HMAC-SHA256 | 对称 | API Key 签名、JWT HS256 | 32 字节 |
| RSA-SHA256 | 非对称 | JWT RS256、OIDC | 256 字节 |
| ECDSA P-256 | 非对称 | 移动端 / IoT Agent | 64 字节 |
| Ed25519 | 非对称 | 高性能 API 签名 | 64 字节 |
调试命令:使用 OpenSSL 快速生成 RSA 密钥对并测试签名。
# 1. 生成私钥
openssl genpkey -algorithm RSA -out private.pem -pkeyopt rsa_keygen_bits:2048
# 2. 提取公钥
openssl pkey -in private.pem -pubout -out public.pem
# 3. 对请求 Body 签名(HMAC 示例)
echo -n "body_content" | openssl dgst -sha256 -hmac "shared_secret" | cut -d' ' -f2
# 4. 验证签名(服务端同理)
3.5 部署与性能优化
- 令牌缓存:JWT 在验证后缓存公钥获取结果,减少外部证书颁发机构(CA)请求。
- Key 轮换策略:使用
kid(Key ID)实现多密钥共存,旧密钥保留一个iat窗口期。 - 拒绝列表(Denylist):对泄露的 API Key 或 JWT jti 使用 Redis 存储,判断时间 O(1)。
- 速率限制:基于 API Key 或令牌的
sub(subject) 实施流控,防止暴力破解。
常见错误:
- JWT 过期后仍允许刷新令牌无限制续命 → 必须验证 refresh_token 是否已撤销。
- API Key 通过 URL Query 明文传输 → 必须使用 Header + HTTPS。
- 签名算法使用
none算法攻击 → 服务端强制限制算法白名单。 - OAuth2 未校验 redirect_uri → 开放重定向漏洞。
3.6 稳定性与生产清单
// 生产环境认证中间件检查项(伪代码)
checklist:
- [x] 所有端点强制 TLS 1.2+
- [x] JWT 签名算法白名单 [RS256, ES256]
- [x] API Key 存储使用 bcrypt(round=12)
- [x] OAuth2 state 参数随机且绑定 session
- [x] 令牌过期时间 ≤ 1h,刷新令牌 ≤ 7d
- [x] 吊销列表使用 TTL 自动过期
四种机制并非互斥:一个生产级 Agent 平台通常使用 OAuth2 获取 JWT,再将 JWT 作为 Bearer Token 传递,底层签名由 RSA 或 ECDSA 保障。API Key 保留作为内部服务间调用的轻量方案。签名算法是整个信任链的根基,密钥管理(HSM / KMS)是部署的最后一道防线。