核心价值使用 `crypto.subtle` 在 Edge 环境中计算与验证 HMAC-SHA256 签名。结合时间戳限制请求时效并采用常数时间比较降低侧信道风险。签名验证实现export const runtime = 'edge'
const SECRET = 'super-secret'
const SKEW = 300
async function hmac(input: ArrayBuffer) {
const enc = new TextEncoder()
const key = await crypto.subtle.importKey('raw', enc.encode(SECRET), { name: 'HMAC', hash: 'SHA-256' }, false, ['sign'])
const mac = await crypto.subtle.sign('HMAC', key, input)
return new Uint8Array(mac)
}
function constantTimeEqual(a: Uint8Array, b: Uint8Array) {
if (a.length !== b.length) return false
let diff = 0
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i]
return diff === 0
}
function parseSig(sig: string) {
const s = sig.replace(/^sha256=/, '')
const raw = atob(s)
const buf = new Uint8Array(raw.length)
for (let i = 0; i < raw.length; i++) buf[i] = raw.charCodeAt(i)
return buf
}
export async function POST(req: Request) {
const ts = Number(req.headers.get('x-timestamp') || 0)
const sig = req.headers.get('x-signature') || ''
if (!ts || !sig) return new Response('Unauthorized', { status: 401 })
const now = Math.floor(Date.now() / 1000)
if (Math.abs(now - ts) > SKEW) return new Response('Expired', { status: 401 })
const body = await req.arrayBuffer()
const enc = new TextEncoder()
const payload = new Uint8Array(enc.encode(ts.toString()).length + body.byteLength)
payload.set(enc.encode(ts.toString()), 0)
payload.set(new Uint8Array(body), enc.encode(ts.toString()).length)
const mac = await hmac(payload.buffer)
const recv = parseSig(sig)
if (!constantTimeEqual(mac, recv)) return new Response('Unauthorized', { status: 401 })
return Response.json({ ok: true }, { headers: { 'Cache-Control': 'no-store' } })
}
治理建议第三方应携带时间戳与签名,签名覆盖时间戳与请求体;服务端校验后再处理业务。重放防护可结合唯一事件 ID 做去重存储,或依赖上游幂等保证;本文示例提供请求时效限制。结论在 Edge 路由中以 HMAC 验证结合时间戳窗口进行入口治理,可显著降低伪造与重放风险,并保持实现的简洁与高性能。

发表评论 取消回复