BOM如何启用WebAuthn功能?
最近发现不少小伙伴都对文章很感兴趣,所以今天继续给大家介绍文章相关的知识,本文《BOM中如何使用WebAuthn功能?》主要内容涉及到等等知识点,希望能帮到你!当然如果阅读本文时存在不同想法,可以在评论中表达,但是请勿使用过激的措辞~
WebAuthn通过navigator.credentials对象实现无密码认证,核心方法是create()和get()。1. 注册时调用create()生成密钥对,私钥存于认证器,公钥发送服务器;2. 登录时调用get()获取签名断言,发送服务器验证身份。其安全性依赖于公钥加密机制,挑战值防止重放攻击,服务器需严格验证签名、来源、RP ID等信息,并检查计数器防克隆。开发中需注意跨域配置、错误处理、兼容性测试及提供备用恢复机制。
在BOM(浏览器对象模型)中操作WebAuthn功能,主要围绕navigator.credentials
这个全局对象展开。它提供了一套标准化的API,允许网页与用户的硬件安全密钥、指纹识别器或面部识别系统等认证器进行交互,从而实现无密码或多因素认证。简而言之,WebAuthn就是通过这个接口,让你的浏览器能“听懂”并“指挥”本地的安全硬件。

解决方案
要实现WebAuthn的注册(创建新凭证)和认证(获取现有凭证),你主要会用到navigator.credentials.create()
和navigator.credentials.get()
这两个方法。这两个方法都返回一个Promise,你需要异步处理它们的结果。
注册(创建凭证):
当用户首次使用WebAuthn注册时,你需要调用navigator.credentials.create()
。这个方法会指示浏览器生成一对新的公钥/私钥,私钥安全地存储在用户的认证器(如指纹传感器、USB密钥)中,而公钥则返回给你的Web应用,你需要将其发送到服务器进行存储。

const publicKeyCredentialCreationOptions = { challenge: Uint8Array.from('一个随机生成的挑战值,每次注册都应不同', c => c.charCodeAt(0)), // 服务器生成的随机数 rp: { name: "我的酷炫网站", // 网站名称 id: "yourdomain.com", // 网站域名,用于防止钓鱼 }, user: { id: Uint8Array.from('用户唯一ID', c => c.charCodeAt(0)), // 用户的唯一标识符 name: "user@example.com", // 用户名 displayName: "示例用户", }, pubKeyCredParams: [{ alg: -7, type: "public-key" }], // 推荐的算法类型,-7代表ES256 timeout: 60000, // 超时时间 attestation: "direct", // 或 "none", "indirect" excludeCredentials: [], // 可选,排除用户已注册的凭证 authenticatorSelection: { authenticatorAttachment: "platform", // "platform" (内置指纹) 或 "cross-platform" (USB密钥) userVerification: "required", // "required", "preferred", "discouraged" }, }; navigator.credentials.create({ publicKey: publicKeyCredentialCreationOptions }) .then(credential => { // 将 credential.response.attestationObject 和 credential.response.clientDataJSON // 以及 credential.id 发送到服务器进行验证和存储 console.log("注册成功:", credential); // 通常需要将 credential.rawId (Base64Url编码), credential.response.clientDataJSON, // credential.response.attestationObject, credential.type 等发送到后端 // 后端会验证这些数据,并存储公钥 }) .catch(error => { console.error("注册失败:", error); // 处理用户取消、超时、不支持等错误 });
认证(获取凭证):
当用户尝试登录时,你需要调用navigator.credentials.get()
。这个方法会提示用户通过他们的认证器(如触摸指纹传感器)来证明身份。成功后,浏览器会返回一个签名过的断言(assertion),你的Web应用需要将其发送到服务器进行验证。
const publicKeyCredentialRequestOptions = { challenge: Uint8Array.from('一个随机生成的挑战值,每次认证都应不同', c => c.charCodeAt(0)), // 服务器生成的随机数 allowCredentials: [], // 可选,指定允许使用的凭证ID列表 timeout: 60000, userVerification: "preferred", // "required", "preferred", "discouraged" }; navigator.credentials.get({ publicKey: publicKeyCredentialRequestOptions }) .then(credential => { // 将 credential.response.authenticatorData, credential.response.clientDataJSON, // credential.response.signature, credential.response.userHandle // 以及 credential.id 发送到服务器进行验证 console.log("认证成功:", credential); // 后端会根据之前存储的公钥,验证这个断言的签名是否有效 }) .catch(error => { console.error("认证失败:", error); // 处理用户取消、超时、不支持等错误 });
WebAuthn认证:无密码登录的魔法与机制
WebAuthn之所以能实现无密码登录,其核心在于它巧妙地利用了公钥密码学。我们不再需要记忆复杂的密码,而是依赖于用户持有的“物理凭证”——一个存储了私钥的安全设备,比如你的手机指纹传感器、Windows Hello,或者一个外置的USB安全密钥(如YubiKey)。

想象一下这个过程:当你在一个支持WebAuthn的网站注册时,你的浏览器会和你的认证器(比如指纹识别器)“商量”一下,然后生成一对加密密钥:一个公钥和一个私钥。私钥就像一把只有你和你的认证器知道的“秘密钥匙”,它永远不会离开你的设备。公钥则像一把可以公开的“锁”,它被发送到网站的服务器上存储起来。
下次你登录时,网站会给你一个随机的“挑战”(challenge),就像一个只有这一次有效的谜题。你的浏览器会把这个谜题发给你的认证器,认证器用它的“秘密钥匙”(私钥)来“解答”这个谜题,并生成一个“答案”(签名),这个答案再发回给网站。网站用它存储的你的“公开锁”(公钥)来验证这个“答案”是否正确。如果答案正确,就证明是你在操作,因为只有拥有那个“秘密钥匙”的认证器才能生成正确的答案。
这个过程中,你的实际“密码”(私钥)从未离开过你的设备,也从未在网络上传输,这极大降低了密码被窃取或钓鱼攻击的风险。这不就是一种优雅的魔法吗?从用户的角度看,只需轻轻一触或一眼扫过,就完成了身份验证,既安全又便捷。
WebAuthn实现中的常见挑战与应对策略
虽然WebAuthn前景光明,但在实际落地过程中,开发者确实会遇到一些让人头疼的“坑”。这不像传统的密码认证那样直白,它涉及到多方协作(浏览器、认证器、RP服务器),以及对公钥密码学的一些理解。
一个最常见的挑战是跨域问题(Cross-Origin Issues)。WebAuthn对rp.id
(Relying Party ID,通常是你的域名)有严格的要求。它必须是当前页面的域名或其可注册的父域。比如,如果你的网站是app.example.com
,那么rp.id
可以是app.example.com
或example.com
。但如果你在dev.example.com
上测试,而rp.id
设置成了prod.example.com
,浏览器就会拒绝操作。这是为了防止钓鱼攻击,但初次接触时很容易混淆。我的建议是,开发和生产环境的rp.id
要仔细匹配,或者在开发时使用与开发域名一致的rp.id
。
其次是用户体验与错误处理。WebAuthn的交互是高度依赖浏览器和操作系统的。用户可能会看到各种提示,比如“请触摸您的安全密钥”、“请验证您的指纹”。如果用户取消了操作、设备不支持、或者认证超时,navigator.credentials.create()
或get()
的Promise就会被拒绝。你需要捕获这些错误,并向用户提供清晰的反馈,而不是简单地抛出一个通用错误信息。例如,DOMException
中的name
属性可以告诉你具体是NotAllowedError
(用户取消)还是SecurityError
(协议问题)。
再来是挑战值(Challenge)的生成和验证。这个挑战值必须是服务器端生成的、加密安全的随机数,并且每次注册或认证都必须是唯一的。它只应使用一次(nonce),以防止重放攻击。如果服务器端没有正确地生成和验证挑战,整个WebAuthn的安全性就形同虚设。这部分是后端的核心安全逻辑,前端只负责传递。
最后,浏览器和设备兼容性也是一个持续的考量。虽然主流浏览器(Chrome, Firefox, Edge, Safari)都支持WebAuthn,但它们对某些特性(如authenticatorSelection.authenticatorAttachment
、attestation
)的支持程度可能有所不同。此外,用户的操作系统版本和硬件认证器类型也会影响功能可用性。在开发时,最好在多种浏览器和设备上进行测试,并考虑提供优雅降级方案,比如在不支持WebAuthn时回退到密码登录。这不像写一个简单的JavaScript函数那样,它需要对整个生态系统有更全面的认识。
确保WebAuthn流程安全的实践与注意事项
WebAuthn的核心价值在于其安全性,但这种安全性并非自动获得,它需要前端和后端协同工作,并遵循一系列最佳实践。如果处理不当,即使是WebAuthn也可能存在漏洞。
一个至关重要的环节是服务器端对认证断言(Assertion)的严格验证。当navigator.credentials.get()
返回一个PublicKeyCredential
对象给前端时,前端必须将其发送到后端。后端不能简单地相信前端传来的数据。它需要:
- 验证签名: 使用注册时存储的公钥来验证断言的签名是否有效。这是最核心的一步,确保了数据未被篡改且来自合法的认证器。
- 验证挑战值: 确保断言中的挑战值与服务器发送给前端的挑战值完全匹配,并且该挑战值是唯一的、未被重用的。
- 验证来源(Origin): 确认断言中的
clientDataJSON.origin
与你的网站域名匹配,防止跨站伪造请求。 - 验证RP ID: 确认
authenticatorData
中的RP ID哈希值与你的网站RP ID匹配。 - 检查标志位: 验证
authenticatorData
中的用户已验证(UV)和用户在场(UP)标志位,确保用户确实进行了交互。 - 计数器检查: 认证器会维护一个签名计数器。服务器应存储这个计数器并在每次认证时验证它是否递增。这可以防止认证器被克隆或重放攻击。
此外,安全存储公钥也至关重要。公钥本身不是秘密,但它们必须与正确的用户关联,并存储在一个安全的数据库中。如果公钥被篡改或丢失,用户的WebAuthn认证将失效。
防止钓鱼攻击是WebAuthn设计的初衷之一,但开发者仍需警惕。rp.id
的正确设置和验证是关键。如果攻击者能诱骗用户在钓鱼网站上进行WebAuthn操作,并成功注册或认证,那将是灾难性的。因此,除了技术实现,对用户的安全教育也同样重要。
最后,提供备用恢复机制是不可忽视的一点。虽然WebAuthn非常安全和方便,但如果用户的认证器丢失、损坏,或者他们无法访问,他们将无法登录。因此,提供传统的密码登录作为备用选项,或者提供基于邮件/短信的恢复流程,都是必要的。这就像给你的房子除了智能锁,还留了一把传统的钥匙,以防万一。毕竟,技术再先进,也得考虑真实世界中的各种“意外”。
终于介绍完啦!小伙伴们,这篇关于《BOM如何启用WebAuthn功能?》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布文章相关知识,快来关注吧!

- 上一篇
- 戴尔Win8系统恢复教程及方法

- 下一篇
- LinuxOpenSSL3.0核心功能解析
-
- 文章 · 前端 | 3小时前 |
- CSSflex布局打造动态时间轴效果
- 165浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- HTML文字竖排设置:writing-mode属性使用教程
- 108浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- JavaScript中forEach遍历数组方法详解
- 389浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- HTML文字居中方法有哪些?
- 352浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- CSS美化数据标签样式—badge组件设计指南
- 209浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- CSS加载动画:旋转与进度条教程
- 393浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- BOM页面OCR识别怎么实现?
- 295浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- JS添加类名的多种方式解析
- 118浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- CSS相邻兄弟选择器用法详解
- 497浏览 收藏
-
- 文章 · 前端 | 3小时前 |
- JavaScript动态生成分组HTML元素方法
- 177浏览 收藏
-
- 文章 · 前端 | 4小时前 |
- HTML获取地理位置方法及GeolocationAPI使用教程
- 130浏览 收藏
-
- 文章 · 前端 | 4小时前 |
- HTML表格调用API的几种方法详解
- 378浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 509次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 497次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 边界AI平台
- 探索AI边界平台,领先的智能AI对话、写作与画图生成工具。高效便捷,满足多样化需求。立即体验!
- 218次使用
-
- 免费AI认证证书
- 科大讯飞AI大学堂推出免费大模型工程师认证,助力您掌握AI技能,提升职场竞争力。体系化学习,实战项目,权威认证,助您成为企业级大模型应用人才。
- 241次使用
-
- 茅茅虫AIGC检测
- 茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
- 358次使用
-
- 赛林匹克平台(Challympics)
- 探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
- 441次使用
-
- 笔格AIPPT
- SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
- 378次使用
-
- 优化用户界面体验的秘密武器:CSS开发项目经验大揭秘
- 2023-11-03 501浏览
-
- 使用微信小程序实现图片轮播特效
- 2023-11-21 501浏览
-
- 解析sessionStorage的存储能力与限制
- 2024-01-11 501浏览
-
- 探索冒泡活动对于团队合作的推动力
- 2024-01-13 501浏览
-
- UI设计中为何选择绝对定位的智慧之道
- 2024-02-03 501浏览