智能工具库

Passkey认证实战:Next.js与NestJS无密码登录

Passkey认证实战:Next.js与NestJS无密码登录
本文教你用WebAuthn、Next.js和NestJS构建无密码登录,涵盖后端注册/认证流程、前端交互及安全避坑,适合全栈开发者。
1来源:freeCodeCamp

为什么密码认证已经过时?

传统的密码登录模式,用户需要记住一串复杂字符,而开发者则需要处理哈希、加盐、限流和找回密码流程。即便如此,密码依然面临两大核心风险:

  • 钓鱼攻击:一个仿冒页面就能骗走密码,用户很难辨别URL的细微差别。
  • 密码复用:大多数人在多个网站重复使用相同密码,一旦某个数据库泄露,撞库攻击就会波及所有账户。

Passkey(通行密钥)正是为解决这些痛点而生。它基于WebAuthn标准,让用户通过设备内置的生物识别(指纹、面容)或PIN完成认证,私钥从不离开设备,服务器只保存公钥。这既消除了记忆密码的负担,也从根本上杜绝了钓鱼——因为伪造页面无法获得设备上的密钥签名。

技术选型与项目结构

本教程采用现代主流全栈方案:

  • 后端:NestJS + PostgreSQL,负责用户与Passkey的存储、注册/认证挑战的生成与验证。
  • 前端:Next.js,提供注册和登录界面,调用浏览器WebAuthn API。
  • 核心库:SimpleWebAuthn,一个维护良好的TypeScript库,封装了WebAuthn的密码学操作与数据解析。

项目分为两个独立应用:backend(NestJS API)和frontend(Next.js),通过REST接口通信。

后端实现:注册与认证流程

1. 注册Passkey

当用户提供邮箱并请求注册时,后端先生成注册选项(包含挑战、依赖方ID等),前端调用navigator.credentials.create()让用户确认生物识别,返回认证器响应。后端再调用SimpleWebAuthn的verifyRegistrationResponse()验证签名,并将公钥和凭证ID存入数据库。

关键步骤:

  • 生成挑战时,确保随机且每次唯一。
  • 验证响应时,检查挑战是否匹配、来源是否可信。
  • 凭证ID需要Base64URL编码存储,避免二进制乱码。

2. 认证(登录)Passkey

登录流程类似:后端生成认证选项,前端调用navigator.credentials.get()获取签名,后端用存储的公钥验证签名。验证通过后签发JWT,前端将其保存在HttpOnly Cookie或内存中,用于后续请求鉴权。

前端交互:从注册到登录

Next.js前端只需两个页面:

  • 注册页:用户输入邮箱,点击“注册”后调用后端API获取注册选项,再触发浏览器原生认证弹窗。成功后显示“注册完成”。
  • 登录页:输入邮箱,点击“登录”,同样触发认证弹窗,成功后跳转至受保护页面。

为了提升体验,务必捕获并展示错误信息,例如用户取消认证、设备不支持WebAuthn等。

安全避坑指南

教程作者特别提醒了四个容易踩的坑:

  1. 重复编码凭证ID:在存储和传输时只编码一次,否则验证时会因格式不匹配而失败。
  2. 用undefined清除挑战:认证完成后,应将会话中的挑战置为undefined而非null,避免类型错误。
  3. 不检查凭证归属:验证认证响应时,必须确认该凭证确实属于当前用户,防止他人凭证被冒用。
  4. 注册时合并已有账户:若邮箱已存在,应明确提示或走绑定流程,而不是默默添加新Passkey,避免账户劫持。

另外,注册时要求用户验证(如设备PIN)是必要的,不要为了流畅而省略。

总结与下一步

通过本教程,你已经掌握了Passkey认证的完整闭环:后端生成挑战、前端调用WebAuthn、后端验证签名、签发JWT。这套方案不仅提升了安全性,也大幅改善了用户体验。

想进一步优化,可以考虑:

  • 增加多设备Passkey同步策略。
  • 使用@simplewebauthn/server的MetadataService验证认证器是否符合FIDO规范。
  • 为旧用户保留密码登录作为降级方案,逐步迁移。

完整源码已发布在GitHub,建议结合官方文档动手实践,才能真正理解WebAuthn的细节。

Roland Mweze

How to Build Passkey Authentication with WebAuthn, Next.js and NestJS

Sign up page with an email field and a

Operating system passkey prompt asking the user to confirm with Touch ID

本文目录(8 节)

本文基于 freeCodeCamp 的公开内容,由 AI 辅助整理改写后发布。

原标题:How to Build Passkey Authentication with WebAuthn, Next.js and NestJS

阅读原文