[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"$fkhBs_5oJuewnzzhqBL9Y_B9bUe2L29wZtV2BD8gWuMc":3},{"item":4,"related":43},{"id":5,"type":6,"title":7,"slug":8,"summary":9,"body":10,"coverUrl":11,"productScreenshots":12,"productLinks":13,"authorName":14,"authorUrl":15,"authorSubject":16,"category":17,"tags":22,"sourceLabel":35,"sourceName":35,"sourceUrl":35,"status":36,"seoTitle":35,"seoDescription":35,"canonicalUrl":35,"isFeatured":37,"sno":38,"sortOrder":39,"publishedAt":40,"updatedAt":41,"createdAt":42},"974096b9-8c0e-431e-bab6-8cd58e2af97f","article","Passkey通行密钥：为什么用指纹登录比密码更安全","passkeys-webauthn-passwordless-login","Passkey 基于 WebAuthn\u002FFIDO，用非对称加密让私钥不出设备、并与域名绑定，从原理上防钓鱼。","你有没有算过自己记了多少个密码？又有多少次因为「忘记密码」而走找回流程？\n\n密码这套用了几十年的登录方式，正在被一种更安全也更省心的机制取代——它叫 Passkey（通行密钥）。用指纹或面容一刷就登录，且从原理上就防钓鱼。\n\n本文讲清它是什么、怎么工作、怎么落地。\n\n## 密码为什么该退休\n\n先说清问题。密码有三个老毛病：容易被猜\u002F被撞库、容易在钓鱼网站被骗走、还要用户自己记。即便加了短信验证码，也挡不住实时钓鱼（攻击者把你输入的验证码即时转发到真网站）。\n\nPasskey 换了个思路。它基于 WebAuthn \u002F FIDO 标准，用的是「非对称加密」——注册时你的设备生成一对钥匙：**私钥**永远留在你的设备里（受指纹\u002F面容\u002FPIN 保护，绝不外传），**公钥**交给网站保存。登录时网站发来一个随机「挑战」，你的设备用私钥签名，网站用公钥验证。整个过程没有任何「秘密」在网络上传输。\n\n## 为什么它天生防钓鱼\n\n这是 Passkey 最关键的优势。每个 Passkey 都和一个具体的网站域名「绑定」。如果你被骗到一个仿冒域名，浏览器根本不会拿出对应的 Passkey——因为域名对不上。也就是说，就算你想上当，技术上也交不出凭证。\n\n```mermaid\nflowchart LR\n    A[注册: 设备生成密钥对] --> B[私钥留设备\u003Cbr\u002F>公钥给网站]\n    B --> C[登录: 网站发随机挑战]\n    C --> D[设备用私钥签名\u003Cbr\u002F>需指纹\u002F面容解锁]\n    D --> E[网站用公钥验证]\n    E --> F((登录成功\u003Cbr\u002F>无秘密上网))\n```\n\n## 一个最小可运行的例子\n\n在网页里，浏览器通过 `navigator.credentials` API 直接对接系统的生物识别。注册和登录各是一次调用：\n\n```javascript\n\u002F\u002F 1) 注册：创建一个 Passkey（options 由你的服务端生成）\nconst cred = await navigator.credentials.create({\n  publicKey: {\n    challenge: serverChallenge,          \u002F\u002F 服务端下发的随机值\n    rp: { name: \"示例站点\", id: \"example.com\" },\n    user: { id: userId, name: \"user@example.com\", displayName: \"小明\" },\n    pubKeyCredParams: [{ type: \"public-key\", alg: -7 }], \u002F\u002F ES256\n    authenticatorSelection: { residentKey: \"required\", userVerification: \"required\" },\n  },\n});\n\u002F\u002F 把 cred 里的公钥等信息发回服务端保存\n\n\u002F\u002F 2) 登录：用已有 Passkey 签名挑战\nconst assertion = await navigator.credentials.get({\n  publicKey: { challenge: serverChallenge, rpId: \"example.com\" },\n});\n\u002F\u002F 把 assertion 发回服务端，用之前存的公钥验证签名\n```\n\n注意：客户端只负责「唤起系统验证 + 拿到签名」，真正的**挑战生成**和**签名验证**必须在服务端完成，且 `challenge` 必须一次性、随机、有时效——这是安全的关键。\n\n## 取舍与边界\n\n- **设备同步与找回**：现代 Passkey 可通过平台账号（如系统钥匙串）在你的设备间同步，换手机不至于全丢；但仍要设计好账号恢复流程，避免用户彻底被锁在外面。\n- **跨生态**：在不同厂商设备\u002F浏览器之间使用时，通常靠「扫码 + 手机」的跨设备流程衔接，体验在持续改善。\n- **过渡期共存**：多数网站会让 Passkey 与密码并存一段时间，逐步引导用户迁移，而不是一刀切。\n- **它保护的是「登录」**：Passkey 解决身份验证，不替代授权、会话管理等其它安全环节。\n\n## Tips\n\n- 新系统做登录，优先支持 Passkey，把密码作为过渡兜底而非唯一选项。\n- 服务端务必保证 `challenge` 随机、一次性、有时效，验证逻辑放服务端。\n- 一定要设计好账号恢复路径（备用邮箱、多设备等），别让用户丢设备就丢账号。\n- 向用户解释「用指纹登录 = 更安全」，降低迁移心理门槛。\n- 记住 Passkey 的核心卖点：私钥不出设备 + 与域名绑定，从原理上防钓鱼。","https:\u002F\u002Fimages.unsplash.com\u002Fphoto-1614064641938-3bbee52942c7?w=1200",[],[],"Foundit AI","https:\u002F\u002Ffoundit.cn","f39339b1-aaa6-4e86-b0c2-a6e6a21113b5",{"id":18,"name":19,"slug":20,"description":21},"6179d3b6-dc34-4483-9ded-3cd9f1b37a47","科普","abbreviation","介绍各领域新兴概念",[23,27,31],{"id":24,"name":25,"slug":26},"144abe77-0dc6-4f66-a176-20bddb1c0bfa","编程","coding",{"id":28,"name":29,"slug":30},"a202d639-99a6-488a-a712-4d4c6ffd7e15","开发","dev",{"id":32,"name":33,"slug":34},"7c76bfc2-f80f-4ee0-a95d-27bd8708b434","技术","slug",null,"published",false,71,0,"2026-07-17T00:00:00.000Z","2026-07-19T17:55:56.818Z","2026-07-19T17:10:50.027Z",[44,54,62],{"id":45,"type":6,"title":46,"slug":47,"summary":48,"coverUrl":49,"authorName":50,"sno":51,"publishedAt":52,"createdAt":53},"153fb92b-ccb1-4311-ad7c-d93b36ea2203","WebAssembly Component Model：不同语言写的模块如何拼在一起？","webassembly-component-model-wasi-explained","WebAssembly 不只是一个能运行的二进制文件。Component Model 通过接口、类型和能力权限，让不同语言编写的组件能够组合。本文从 WIT、WASI 0.2 和宿主运行时讲清组件模型的价值、权限边界与适用场景。","\u002Fuploads\u002F2026-09-08\u002Fb44135d7-7561-477f-9edc-c52fd17b99f4.jpg","Foundit",51,"2026-09-08T00:00:00.000Z","2026-09-08T03:19:21.154Z",{"id":55,"type":6,"title":56,"slug":57,"summary":58,"coverUrl":59,"authorName":14,"sno":60,"publishedAt":40,"createdAt":61},"ea23e2ef-cc1b-4977-ad38-bf95b363c953","SQLite复兴：从一个文件到边缘数据库","sqlite-libsql-turso-edge-database","SQLite 是没有服务器、就是一个文件的嵌入式数据库，零运维、极低延迟。借助 libSQL \u002F Turso，它正走向「边缘 + 多副本」，让读多写少的应用全球低延迟。","https:\u002F\u002Foxqtewbrpuiouqqjrvdv.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Fpublic-media\u002F2026-07-19\u002F611d83bb-2a21-4271-a183-155a89a5bb81.jpg",70,"2026-07-19T17:10:52.499Z",{"id":63,"type":6,"title":64,"slug":65,"summary":66,"coverUrl":67,"authorName":50,"sno":68,"publishedAt":69,"createdAt":70},"54d83c94-d588-400d-9d13-42daa20331e2","CAS：文件的身份可以由内容决定","content-addressable-storage-ai-coding","内容寻址存储 CAS 用内容摘要识别文件和构建产物，解释 AI 编程工具、容器和缓存为什么能复用结果。","\u002Fuploads\u002F2026-09-14\u002F3fab23b3-8bcd-4a3b-bf5a-2ab895ce3a10.jpg",41,"2026-09-14T00:00:00.000Z","2026-09-14T15:01:41.114Z"]