---

title: Magic Link无密码登录治理(签名/一次性/过期窗口)最佳实践

keywords:

  • Magic Link
  • HMAC
  • 过期窗口
  • 一次性
  • nonce
  • origin白名单

description: 通过HMAC签名的一次性Magic Link与过期窗口、origin白名单校验,安全落地无密码登录并阻断链接滥用与重放。

categories:

  • 文章资讯
  • 编程技术

---

背景与价值

Magic Link降低密码负担,但若无签名与一次性治理易被滥用。统一签名、白名单与窗口策略可保障安全。

统一规范

  • 一次性:链接含 nonce,验证后立即作废。
  • 过期窗口:exp 不超过15分钟,过期拒绝。
  • 来源白名单:链接跳转 origin 必须受控。

核心实现

签名生成与校验

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; sig: string }
const store = new Set<string>()
const allowOrigins = new Set(['https://app.example.com'])

function genId(): string { return Math.random().toString(36).slice(2) }
function now(): number { return Date.now() }

async function issueLink(email: string, key: CryptoKey, ttlMs = 900000): Promise<Token> { const t: Omit<Token,'sig'> = { email, nonce: genId(), exp: now() + ttlMs }; const payload = `${t.email}|${t.nonce}|${t.exp}`; 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 verifyLink(t: Token, key: CryptoKey, redirect: string): Promise<boolean> { if (!originAllowed(redirect)) return false; if (!store.has(t.nonce)) return false; if (now() > t.exp) return false; const payload = `${t.email}|${t.nonce}|${t.exp}`; const expect = await hmac(key, payload); const ok = expect === t.sig; if (ok) store.delete(t.nonce); return ok }

落地建议

  • 对链接实行一次性与过期窗口治理,并绑定跳转来源白名单。
  • 审计签发与验证事件,失败立即告警并阻断。

验证清单

  • nonce 是否一次性使用且过期后拒绝。
  • 跳转 origin 是否命中白名单,签名是否匹配。

点赞(0) 打赏

评论列表 共有 0 条评论

暂无评论
立即
投稿

微信公众账号

微信扫一扫加关注

发表
评论
返回
顶部