背景与价值重置链接常被攻击者滥用。一次性与设备绑定策略可大幅降低风险并提升可追踪性。统一规范一次性与过期:包含 `nonce/exp`,验证后立即作废;期限≤15分钟。设备绑定:与发起设备指纹绑定,回调需一致。来源白名单:仅允许受控域名的回调来源。核心实现签发与验证function enc(s: string): Uint8Array { return new TextEncoder().encode(s) } async function importHmac(secret: ArrayBuffer): Promise<CryptoKey> { return crypto.subtle.importKey('raw', secret, { name: 'HMAC', hash: 'SHA-256' }, false, ['sign']) } async function hmac(key: CryptoKey, data: string): Promise<string> { const raw = await crypto.subtle.sign('HMAC', key, enc(data)); const u = new Uint8Array(raw); let s=''; for (let i=0;i<u.length;i++) s+=String.fromCharCode(u[i]); return btoa(s).replace(/\+/g,'-').replace(/\//g,'_').replace(/=+$/,'') } type Token = { email: string; nonce: string; exp: number; device: string; sig: string } const store = new Set<string>() const allowOrigins = new Set(['https://app.example.com']) function gen(): string { return Math.random().toString(36).slice(2) } function now(): number { return Date.now() } async function issue(email: string, device: string, key: CryptoKey, ttlMs = 900000): Promise<Token> { const t: Omit<Token,'sig'> = { email, nonce: gen(), exp: now() + ttlMs, device }; const payload = `${t.email}|${t.nonce}|${t.exp}|${t.device}`; const sig = await hmac(key, payload); store.add(t.nonce); return { ...t, sig } } function originAllowed(url: string): boolean { try { const u = new URL(url); return allowOrigins.has(u.origin) } catch { return false } } async function verify(t: Token, device: string, key: CryptoKey, redirect: string): Promise<boolean> { if (!originAllowed(redirect)) return false; if (!store.has(t.nonce)) return false; if (now() > t.exp) return false; if (device !== t.device) return false; const payload = `${t.email}|${t.nonce}|${t.exp}|${t.device}`; const expect = await hmac(key, payload); const ok = expect === t.sig; if (ok) store.delete(t.nonce); return ok } 落地建议重置链接采用一次性令牌与短期过期,并与发起设备绑定;验证后立即作废。回调来源严格白名单并审计失败与异常请求。验证清单`nonce` 是否一次性使用且过期后拒绝;设备指纹是否一致;来源是否命中白名单。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部
2.067233s