ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

轻量鉴权:基于 HMAC 签名的 API 认证

轻量鉴权:基于 HMAC 签名的 API 认证 轻量鉴权基于 HMAC 签名的 API 认证在构建微服务间通信、外部 Webhook 回调或轻量单体系统对外开放的 API 时很多团队一上来就照搬复杂的 OAuth2、IdentityServer 或者是带有一堆配置的 JWT 刷新体系。对于简单的服务端对服务端S2S调用或者轻量 API 授权来说引入庞大的授权中心不仅拉长了调用链路还增加了多余的数据库或 Redis 查询。源自亚马逊 AWS 和 GitHub Webhook 的“HMACHash-based Message Authentication Code签名认证”机制仅需双方共享一个密钥Secret通过哈希算法就能实现防伪造、防篡改、防重放攻击的高安全轻量鉴权。HMAC 签名认证的核心原理客户端在发起请求时并不在网络上传输明文密钥而是将当前时间戳Timestamp、随机数Nonce、HTTP 请求方法、路径及请求体哈希拼接成待签名字符串SignString使用双方约定的SecretKey利用HMAC-SHA256算法计算签名将签名和元数据放入请求头如X-Signature、X-Timestamp、X-Nonce发送给服务端服务端按相同的规则重新计算签名如果匹配且时间戳在允许窗口内如 5 分钟内则认为鉴权通过。50 行通用 TypeScript 实现客户端签名生成import { createHmac, createHash } from node:crypto; export function generateHmacHeaders( accessKey: string, secretKey: string, method: string, path: string, body: string ) { const timestamp Date.now().toString(); const nonce Math.random().toString(36).substring(2, 15); // 计算请求体 SHA256 哈希防止内容被篡改 const bodyHash createHash(sha256).update(body).digest(hex); // 构造规范化签名串 const signString ${method.toUpperCase()}\n${path}\n${timestamp}\n${nonce}\n${bodyHash}; // 计算 HMAC-SHA256 签名 const signature createHmac(sha256, secretKey) .update(signString) .digest(hex); return { X-Access-Key: accessKey, X-Timestamp: timestamp, X-Nonce: nonce, X-Signature: signature, }; }服务端中间件验证拦截export function verifyHmacSignature( secretKey: string, headers: Recordstring, string | undefined, method: string, path: string, body: string ): { valid: boolean; reason?: string } { const timestamp headers[x-timestamp]; const nonce headers[x-nonce]; const signature headers[x-signature]; if (!timestamp || !nonce || !signature) { return { valid: false, reason: 缺少必要签名请求头 }; } // 1. 防重放攻击检查时间戳是否在 5 分钟300秒内 const now Date.now(); const reqTime parseInt(timestamp, 10); if (isNaN(reqTime) || Math.abs(now - reqTime) 300000) { return { valid: false, reason: 请求时间戳已过期或与服务器时间偏差过大 }; } // 2. 服务端按完全相同的规则计算期望签名 const bodyHash createHash(sha256).update(body).digest(hex); const signString ${method.toUpperCase()}\n${path}\n${timestamp}\n${nonce}\n${bodyHash}; const expectedSignature createHmac(sha256, secretKey) .update(signString) .digest(hex); // 3. 安全对比防时序攻击 if (signature ! expectedSignature) { return { valid: false, reason: 签名校验失败 }; } return { valid: true }; }生产安全细节防重放攻击Nonce 幂等服务端可以将已处理过的Nonce存入内存 Set设置 5 分钟自动清理。如果同一 Nonce 在 5 分钟内再次出现直接拒绝。恒定时间对比Timing Attack Protection对比签名时建议使用 Node.js 原生的crypto.timingSafeEqual避免根据字符串对比返回时间长短被黑客推算签名。总结极简架构推崇的是“适度安全”。HMAC 机制不需要依赖任何外部鉴权中间件纯本地纳秒级哈希计算是 API 对接最干净利落的防御方案。
返回列表