BOM中如何操作浏览器的WebAuthn功能?

webauthn通过navigator.credentials对象实现无密码认证,核心方法是create()和get()。1. 注册时调用create()生成密钥对,私钥存于认证器,公钥发送服务器;2. 登录时调用get()获取签名断言,发送服务器验证身份。其安全性依赖于公钥加密机制,挑战值防止重放攻击,服务器需严格验证签名、来源、rp id等信息,并检查计数器防克隆。开发中需注意跨域配置、错误处理、兼容性测试及提供备用恢复机制。

BOM中如何操作浏览器的WebAuthn功能?

在BOM(浏览器对象模型)中操作WebAuthn功能,主要围绕navigator.credentials这个全局对象展开。它提供了一套标准化的API,允许网页与用户的硬件安全密钥、指纹识别器或面部识别系统等认证器进行交互,从而实现无密码或多因素认证。简而言之,WebAuthn就是通过这个接口,让你的浏览器能“听懂”并“指挥”本地的安全硬件。

BOM中如何操作浏览器的WebAuthn功能?

解决方案

要实现WebAuthn的注册(创建新凭证)和认证(获取现有凭证),你主要会用到navigator.credentials.create()navigator.credentials.get()这两个方法。这两个方法都返回一个Promise,你需要异步处理它们的结果。

注册(创建凭证):当用户首次使用WebAuthn注册时,你需要调用navigator.credentials.create()。这个方法会指示浏览器生成一对新的公钥/私钥,私钥安全地存储在用户的认证器(如指纹传感器、USB密钥)中,而公钥则返回给你的Web应用,你需要将其发送到服务器进行存储。

BOM中如何操作浏览器的WebAuthn功能?

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)。

BOM中如何操作浏览器的WebAuthn功能?

想象一下这个过程:当你在一个支持WebAuthn的网站注册时,你的浏览器会和你的认证器(比如指纹识别器)“商量”一下,然后生成一对加密密钥:一个公钥和一个私钥。私钥就像一把只有你和你的认证器知道的“秘密钥匙”,它永远不会离开你的设备。公钥则像一把可以公开的“锁”,它被发送到网站的服务器上存储起来。

下次你登录时,网站会给你一个随机的“挑战”(challenge),就像一个只有这一次有效的谜题。你的浏览器会把这个谜题发给你的认证器,认证器用它的“秘密钥匙”(私钥)来“解答”这个谜题,并生成一个“答案”(签名),这个答案再发回给网站。网站用它存储的你的“公开锁”(公钥)来验证这个“答案”是否正确。如果答案正确,就证明是你在操作,因为只有拥有那个“秘密钥匙”的认证器才能生成正确的答案。

这个过程中,你的实际“密码”(私钥)从未离开过你的设备,也从未在网络上传输,这极大降低了密码被窃取或钓鱼攻击的风险。这不就是一种优雅的魔法吗?从用户的角度看,只需轻轻一触或一眼扫过,就完成了身份验证,既安全又便捷。

WebAuthn实现中的常见挑战与应对策略

虽然WebAuthn前景光明,但在实际落地过程中,开发者确实会遇到一些让人头疼的“坑”。这不像传统的密码认证那样直白,它涉及到多方协作(浏览器、认证器、RP服务器),以及对公钥密码学的一些理解。

一个最常见的挑战是跨域问题(Cross-Origin Issues)。WebAuthn对rp.id(Relying Party ID,通常是你的域名)有严格的要求。它必须是当前页面的域名或其可注册的父域。比如,如果你的网站是app.example.com,那么rp.id可以是app.example.comexample.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.authenticatorAttachmentattestation)的支持程度可能有所不同。此外,用户的操作系统版本和硬件认证器类型也会影响功能可用性。在开发时,最好在多种浏览器和设备上进行测试,并考虑提供优雅降级方案,比如在不支持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功能?的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1508535.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
Node.js 中如何获取连接关闭时的详细错误信息
上一篇 2025年12月20日 04:56:19
JavaScript中的模板字符串是什么?怎么用?
下一篇 2025年12月20日 04:56:29

相关推荐

  • 修复Django电商项目中AJAX过滤产品列表图片不显示问题

    在Django电商项目中,当使用AJAX动态加载过滤后的产品列表时,常遇到图片无法正常显示的问题。这通常是由于前端模板中图片加载方式(如data-setbg属性结合JavaScript库)与AJAX动态内容更新机制不兼容所致。解决方案是直接在AJAX返回的HTML中使用标准的标签来渲染图片,确保浏览…

    2026年5月10日
    000
  • Matplotlib 地图中多类型图例的创建与优化

    Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化Matplotlib 地图中多类型图例的创建与优化

    本教程旨在解决matplotlib地图可视化中,如何在一个图例中同时展示颜色块(如区域分类)和自定义标记(如特定兴趣点)的问题。文章详细介绍了当传统`patch`对象无法正确显示标记时,如何利用`matplotlib.lines.line2d`创建标记图例句柄,并将其与颜色块图例句柄合并,从而生成一…

    2026年5月10日 用户投稿
    100
  • Golang JSON序列化:控制敏感字段暴露的最佳实践

    本教程探讨golang中如何高效控制结构体字段在json序列化时的可见性。当需要将包含敏感信息的结构体数组转换为json响应时,通过利用`encoding/json`包提供的结构体标签,特别是`json:”-“`,可以轻松实现对特定字段的忽略,从而避免敏感数据泄露,确保api…

    2026年5月10日
    000
  • 怎么在PHP代码中实现图片上传功能_PHP图片上传功能实现与安全处理教程

    首先创建含enctype的HTML表单,再用PHP接收文件,检查目录、移动临时文件,验证类型与大小,生成唯一文件名,并调整php.ini限制以确保上传成功。 如果您尝试在PHP项目中添加图片上传功能,但服务器无法正确接收或保存文件,则可能是由于表单配置、文件处理逻辑或安全限制的问题。以下是实现该功能…

    2026年5月10日
    100
  • 比特币新手教程 比特币交易平台有哪些

    比特币是一种去中心化的数字货币,基于区块链技术实现点对点交易,具有匿名性、有限发行和不可篡改等特点;新手可通过交易所购买,P2P交易获得比特币,常用平台包括Binance、OKX和Huobi;交易流程包括注册账户、实名认证、绑定支付方式、充值法币并下单购买,可选择市价单或限价单;比特币存储方式有交易…

    2026年5月10日
    000
  • c++中的SFINAE技术是什么_c++模板编程中的SFINAE原理与应用

    SFINAE 是“替换失败不是错误”的原则,指模板实例化时若参数替换导致错误,只要存在其他合法候选,编译器不报错而是继续重载决议。它用于条件启用模板、类型检测等场景,如通过 decltype 或 enable_if 控制函数重载,实现类型特征判断。尽管 C++20 引入 Concepts 简化了部分…

    2026年5月10日
    000
  • Go语言mgo查询构建:深入理解bson.M与日期范围查询的正确实践

    本文旨在解决go语言mgo库中构建复杂查询时,特别是涉及嵌套`bson.m`和日期范围筛选的常见错误。我们将深入剖析`bson.m`的类型特性,解释为何直接索引`interface{}`会导致“invalid operation”错误,并提供一种推荐的、结构清晰的代码重构方案,以确保查询条件能够正确…

    2026年5月10日
    100
  • vscode上怎么运行html_vscode上运行html步骤【指南】

    首先保存文件为.html格式,再通过浏览器或Live Server插件打开预览;推荐安装Live Server实现本地服务器运行与实时刷新,提升开发体验。 在 VS Code 上运行 HTML 文件并不需要复杂的配置,只需几个简单步骤即可预览页面效果。VS Code 本身是一个代码编辑器,不直接运行…

    2026年5月10日
    100
  • RichHandler与Rich Progress集成:解决显示冲突的教程

    在使用rich库的`richhandler`进行日志输出并同时使用`progress`组件时,可能会遇到显示错乱或溢出问题。这通常是由于为`richhandler`和`progress`分别创建了独立的`console`实例导致的。解决方案是确保日志处理器和进度条组件共享同一个`console`实例…

    2026年5月10日
    000
  • 修复点击时按钮抖动:CSS垂直对齐实践

    本文探讨了在Web开发中,交互式按钮(如播放/暂停按钮)在点击时发生意外垂直位移的问题。通过分析CSS样式变化对元素布局的影响,我们发现这是由于按钮不同状态下的边框样式和内边距改变,以及默认的垂直对齐行为共同作用所致。核心解决方案是利用CSS的vertical-align属性,将其设置为middle…

    2026年5月10日
    100
  • Golang goroutine与channel调试技巧

    使用go run -race检测数据竞争,结合runtime.NumGoroutine监控协程数量,通过pprof分析阻塞调用栈,利用select超时避免永久阻塞,有效排查goroutine泄漏、死锁和数据竞争问题。 Go语言的goroutine和channel是并发编程的核心,但它们也带来了调试上…

    2026年5月10日
    000
  • 使用 Jupyter Notebook 进行探索性数据分析

    Jupyter Notebook通过单元格实现代码与Markdown结合,支持数据导入(pandas)、清洗(fillna)、探索(matplotlib/seaborn可视化)、统计分析(describe/corr)和特征工程,便于记录与分享分析过程。 Jupyter Notebook 是进行探索性…

    2026年5月10日
    000
  • 《魔兽世界》将于6月11日开启国服回归技术测试

    《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试《魔兽世界》将于6月11日开启国服回归技术测试

    《%ign%ignore_a_1%re_a_1%》官方宣布,将于6月11日开启国服回归技术测试,时间为7天,并称可以在6月内正式开服,玩家们可以访问官网下载战网客户端并预下载“巫妖王之怒”客户端,技术测试详情见下图。 WordAi WordAI是一个AI驱动的内容重写平台 53 查看详情 以上就是《…

    2026年5月10日 用户投稿
    200
  • 如何在HTML中插入表单元素_HTML表单控件与输入类型使用指南

    HTML表单通过标签构建,包含action和method属性定义数据提交目标与方式,常用input类型如text、password、email等适配不同输入需求,配合label、required、placeholder提升可用性,结合textarea、select、button等控件实现完整交互,是…

    2026年5月10日
    100
  • 前端缓存策略与JavaScript存储管理

    根据数据特性选择合适的存储方式并制定清晰的读写与清理逻辑,能显著提升前端性能;合理运用Cookie、localStorage、sessionStorage、IndexedDB及Cache API,结合缓存策略与定期清理机制,可在保证用户体验的同时避免安全与性能隐患。 前端缓存和JavaScript存…

    2026年5月10日
    200
  • HTML5网页如何实现手势操作 HTML5网页移动端交互的处理技巧

    首先利用原生touch事件实现滑动判断,再通过preventDefault解决滚动冲突,接着引入Hammer.js处理复杂手势,最后通过优化点击区域、避免事件冲突和增加视觉反馈提升体验。 在移动端浏览器中,HTML5网页可以通过触摸事件实现手势操作,提升用户体验。虽然原生JavaScript提供了基…

    2026年5月10日
    000
  • 创建指定大小并填充特定数据的Golang文件教程

    本文将介绍如何使用Golang创建一个指定大小的文件,并用特定数据填充它。我们将使用 `os` 包提供的函数来创建和截断文件,从而实现快速生成大文件的目的。示例代码展示了如何创建一个10MB的文件,并将其填充为全零数据。掌握这些方法,可以方便地在例如日志系统或磁盘队列等场景中,预先创建测试文件或初始…

    2026年5月10日
    000
  • Python命令怎样使用profile分析脚本性能 Python命令性能分析的基础教程

    使用Python的cProfile模块分析脚本性能最直接的方式是通过命令行执行python -m cProfile your_script.py,它会输出每个函数的调用次数、总耗时、累积耗时等关键指标,帮助定位性能瓶颈;为进一步分析,可将结果保存为文件python -m cProfile -o ou…

    2026年5月10日
    000
  • 使用 WebCodecs VideoDecoder 实现精确逐帧回退

    本文档旨在解决在使用 WebCodecs VideoDecoder 进行视频解码时,实现精确逐帧回退的问题。通过比较帧的时间戳与目标帧的时间戳,可以避免渲染中间帧,从而提高用户体验。本文将提供详细的解决方案和示例代码,帮助开发者实现精确的视频帧控制。 在使用 WebCodecs VideoDecod…

    2026年5月10日
    000
  • 如何插入查询结果数据_SQL插入Select查询结果方法

    如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法如何插入查询结果数据_SQL插入Select查询结果方法

    使用INSERT INTO…SELECT语句可高效插入数据,通过NOT EXISTS、LEFT JOIN、MERGE语句或唯一约束避免重复;表结构不一致时可通过别名、类型转换、默认值或计算字段处理;结合存储过程可提升可维护性,支持参数化与动态SQL。 将查询结果数据插入到另一个表中,可以…

    2026年5月10日 用户投稿
    000

发表回复

登录后才能评论
关注微信