背景与价值二维码登录提升体验但存在重放风险。挑战与一次性确认绑定可保障安全与可追溯。统一规范挑战:包含唯一ID与过期时间;展示端与扫描端一致校验。一次性:确认成功后立即作废挑战。会话绑定:确认与登录会话绑定并记录设备指纹。核心实现挑战与确认type Challenge = { id: string; exp: number; nonce: string } const store = new Map<string, Challenge>() function now(): number { return Date.now() } function gen(): string { return Math.random().toString(36).slice(2) } function issue(ttlMs = 60000): Challenge { const c = { id: gen(), exp: now() + ttlMs, nonce: gen() }; store.set(c.id, c); return c } function take(id: string): Challenge | null { const c = store.get(id) || null; if (c) store.delete(id); return c } type ConfirmReq = { id: string; nonce: string; device: string } type Session = { id: string; device: string; createdAt: number } const byUser = new Map<string, Session[]>() function bind(userId: string, device: string): Session { const s = { id: gen(), device, createdAt: now() }; const list = byUser.get(userId) || []; list.push(s); byUser.set(userId, list); return s } function confirm(userId: string, req: ConfirmReq): Session | null { const c = take(req.id); if (!c) return null; if (now() > c.exp) return null; if (req.nonce !== c.nonce) return null; return bind(userId, req.device) } 落地建议展示端生成挑战并嵌入二维码,扫描端提交确认时校验ID/nonce与过期窗口。确认成功立即作废挑战并绑定会话,记录设备指纹与审计。验证清单挑战是否一次性且过期后拒绝;会话是否成功绑定并记录设备指纹。

发表评论 取消回复