一、基线与风险风险:伪造请求、密钥泄露重放、时钟漂移放大、缓存链路污染。基线:固定算法与头字段、时间戳与窗口校验、nonce唯一性与回收、体内容规范化。二、签名生成import crypto from 'crypto' function b64url(input: Buffer): string { return input.toString('base64').replace(/=/g,'').replace(/\+/g,'-').replace(/\//g,'_') } function signWebhook(body: string, tsSec: number, nonce: string, secret: Buffer): string { const data = `${tsSec}.${nonce}.${body}` const mac = crypto.createHmac('sha256', secret).update(data).digest() return b64url(mac) } 三、服务端校验与重放窗口type Req = { headers: Record<string, string | undefined>; rawBody: string } type Res = { status: (n: number) => Res; end: (b?: string) => void } class NonceStore { keep = new Set<string>() add(n: string) { this.keep.add(n) } has(n: string): boolean { return this.keep.has(n) } del(n: string) { this.keep.delete(n) } } function nowSec(): number { return Math.floor(Date.now()/1000) } function verifyWebhook(req: Req, res: Res, secret: Buffer, windowSec: number, nonces: NonceStore): boolean { const sig = req.headers['x-signature'] || '' const ts = Number(req.headers['x-timestamp'] || '0') const nonce = req.headers['x-nonce'] || '' if (!Number.isFinite(ts)) return false if (Math.abs(nowSec() - ts) > windowSec) return false if (nonces.has(nonce)) return false const expect = signWebhook(req.rawBody, ts, nonce, secret) if (expect !== sig) return false nonces.add(nonce) return true } 四、整合与验收function guardWebhook(req: Req, res: Res, secret: Buffer, store: NonceStore) { const ok = verifyWebhook(req, res, secret, 300, store) if (!ok) return res.status(401).end('invalid_signature') } 头字段:`X-Signature/X-Timestamp/X-Nonce`;窗口≤`300`;`nonce`一次性。签名覆盖顺序为`ts.nonce.body`,体需为规范化字符串;失败时拒绝且记录审计。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
1.938342s