分类: Web

  • 无用户名登录的 WebAuthn 实现

    无用户名登录是一种通过 WebAuthn 进行身份验证的改进方法,其目标是进一步简化用户的登录过程,消除输入用户名的需求。这一特性主要依赖于 Resident Key(驻留密钥)功能,允许认证器在本地存储私钥,从而实现用户身份的无缝识别。下面是这一过程的详细解释:

    为什么普通的 WebAuthn 不能实现无用户名登录?

    在传统的 WebAuthn 流程中,依赖方(如网站)在验证用户身份时需要提供凭证 ID(Credential ID)给认证器,认证器依赖该凭证 ID 计算出相应的私钥。通常,认证器并不存储私钥,而是通过 Key Warp 等技术加密私钥并将其包含在凭证 ID 中。这意味着认证器可以无限制地生成公私钥对,而无需维护庞大的存储空间。

    然而,这也导致了一个问题:在登录时,依赖方必须通过用户名找到对应的凭证 ID,并将其发送给认证器。这就要求用户在验证时必须输入用户名。

    Resident Key(驻留密钥)解决方案

    Resident Key 功能允许认证器在本地永久存储私钥,从而消除对凭证 ID 的依赖。通过这种方式,认证器可以直接根据依赖方 ID 找到对应的私钥进行身份验证,无需用户输入用户名。

    无用户名登录的具体流程

    注册时(启用 Resident Key):

    1. 依赖方请求新建凭证
      • 依赖方请求认证器生成一对公私钥,并要求启用 Resident Key。
    2. 认证器生成密钥对
      • 认证器生成一对公私钥,并将私钥存储在永久内存中,与依赖方 ID 和用户 ID 绑定。
    3. 发送公钥给依赖方
      • 认证器将公钥发送给依赖方,依赖方将公钥与用户 ID 绑定并存储。

    验证时(无用户名登录):

    1. 依赖方请求验证
      • 依赖方请求验证用户身份,只需提供依赖方 ID。
    2. 用户选择认证器
      • 用户选择用于验证的认证器。
    3. 认证器查找私钥
      • 认证器根据依赖方 ID 查找对应的私钥。如果有多个对应的私钥,认证器会提示用户选择使用哪个身份信息进行登录
    4. 认证器签名挑战
      • 认证器使用找到的私钥签名依赖方发送的挑战(challenge),并将签名结果和用户 ID 返回给依赖方。
    5. 依赖方验证签名
      • 依赖方根据返回的用户 ID 查找对应的公钥,验证签名的正确性。如果签名有效,则允许用户登录。

    无用户名登录的示意图

    依赖方                  客户端                 认证器
      |-- 验证请求(依赖方 ID) -->|                          |
      |                           |-- 用户选择认证器 ------>|
      |                           |                          |-- 查找私钥
      |                           |                          |-- 签名挑战
      |                           |<-- 返回签名和用户 ID --|
      |<-- 验证签名(公钥验证) --|                          |
      |-- 登录成功(如验证通过) -->|                          |

    重要注意事项

    • 存储限制:认证器能永久存储的私钥数量是有限的,因此 Resident Key 功能应仅在真正需要无用户名登录时启用。
    • 兼容性:目前尚无统一的方法检测认证器是否支持 Resident Key 功能,因此在无用户名验证失败时,应回退至常规的 WebAuthn 验证流程,即向用户询问用户名。
    • 安全性:驻留密钥功能要求认证器支持用户身份的安全管理,包括对用户 ID 的安全存储和私钥的安全签名操作。

    结论

    Resident Key 功能为 WebAuthn 提供了无用户名登录的可能性,进一步简化了用户的登录体验。在未来,随着更多认证器对 Resident Key 的支持及其在实际应用中的普及,无用户名登录有望成为一种常见的身份验证方法。然而,在实施这一特性时,需要注意认证器的存储限制和兼容性问题,以确保用户体验的平滑过渡。

  • Server-Sent Events(服务器发送事件)和WebSocket(网络套接字)

    Server-Sent Events(服务器发送事件)和WebSocket(网络套接字)是两种常用的实时通信协议,用于在应用程序中进行快速高效的数据传输。它们在实时体验方面的期望随着时间的推移不断增长,随着技术的改进和对可能性的理解而不断提高。本文将比较这两种流行的实时协议——WebSockets和Server-Sent Event(SSE)API。您将了解到它们各自的功能、优缺点以及何时使用它们。

    WebSockets是建立在设备的TCP/IP协议栈之上的一种轻量级传输层,提供了服务器和浏览器之间全双工、低延迟、事件驱动的连接。这对于实时应用程序非常理想,因为在初始的HTTP握手之后,单个WebSocket连接可以处理一个会话的所有消息,无需进一步的握手。当会话结束时,连接应该作为清理的一部分关闭。[2]

    WebSockets的优点包括:

    • 使用自定义的ws协议传输消息,工作在比HTTP更低的层级上。
    • 连接是双向的,因此WebSockets非常适用于需要从服务器读取和写入数据的应用程序,例如聊天应用程序或多人游戏。
    • 它可以复杂地从头开始实现WebSocket,但有许多库可用于简化此过程。
    • 基于事件的,无需轮询即可获取消息,有助于减少延迟。
    • RFC 6455 – WebSocket协议于2011年发布在IETF网站上,现在所有主流浏览器都支持它。[2]

    WebSockets的缺点包括:

    • 防火墙阻塞:一些企业防火墙在处理WebSockets时可能会出现问题(特别是SophosXG防火墙、WatchGuard和McAfee Web Gateway)。
    • 没有内置的重新连接支持:当WebSocket连接关闭时(例如由于网络问题),客户端不会尝试重新连接到服务器,这意味着您需要编写额外的代码来轮询服务器,在可用时重新建立连接。或者,您可以使用Server-Sent Events或具有重新连接支持的库,如Socket.IO。[2]

    Server-Sent Events(SSE)基于Server-Sent DOM Events(服务器发送的DOM事件)。浏览器可以使用EventSource接口订阅服务器生成的事件流,每当发生新事件时,就会接收到更新。EventSource接受来自特定URL的HTTP事件流连接,并在检索到可用数据时保持连接打开。Server-Sent Events是一种标准,描述了服务器在建立初始客户端连接后如何保持数据传输到客户端。它提供了一种内存高效的XHR流实现。与原始的XHR连接不同,原始XHR连接在连接断开之前会缓冲整个接收到的响应,而SSE连接可以在不累积所有消息的情况下丢弃已处理的消息。[3]

    Server-Sent Events的优点包括:

    • 可以在不支持它的浏览器中使用JavaScript进行polyfill。这对于向后兼容性非常有用,因为您可以依赖现有的实现而不必编写替代实现。
    • 内置的重新连接支持:Server-Sent Event连接在连接丢失后会重新建立连接,这意味着需要编写的代码更少,以实现基本的行为。
    • 不会被防火墙阻塞:SSE在进行数据包检查的企业防火墙中没有问题,这对于在企业环境中支持应用程序非常重要。

    Server-Sent Events(SSE)是一种基于服务器发送的DOM事件的协议。浏览器可以通过EventSource接口订阅由服务器生成的事件流,每当发生新事件时,浏览器就会接收到更新。SSE使用XHR流传输消息,连接是单向的,适用于只需要从服务器读取数据的应用程序,例如实时股票或新闻滚动。

    WebSocket是建立在设备的TCP/IP协议栈之上的一种轻量级传输层,提供了全双工、低延迟、事件驱动的服务器与浏览器之间的连接。WebSocket适用于需要从服务器读取和写入数据的应用程序,例如聊天应用程序或多人游戏。

    下面是Server-Sent Events和WebSocket的一些比较:

    Server-Sent Events:

    • 使用XHR流传输消息,连接是单向的。
    • 不需要复杂的实现,但相关的库较少。
    • 事件驱动,无需轮询即可拦截消息。
    • 支持自动重新连接,当连接丢失时会重新建立连接。
    • 可以通过JavaScript进行polyfill,以支持不支持SSE的浏览器。
    • 不受企业防火墙的阻塞,适用于企业环境。

    WebSocket:

    • 使用自定义的ws协议传输消息,工作在比HTTP更低的层级。
    • 连接是双向的,适用于需要从服务器读取和写入数据的应用程序。
    • 实现WebSocket可能较为复杂,但有许多库可用于简化实现。
    • 事件驱动,无需轮询即可拦截消息。
    • 不受企业防火墙的阻塞,但某些企业防火墙可能无法处理WebSocket。
    • 没有内置的重新连接支持,需要额外的代码来重新建立连接。

    根据具体的应用场景和需求,可以选择使用Server-Sent Events或WebSocket。如果只需要从服务器读取数据,并且需要自动重新连接的功能,可以选择Server-Sent Events。如果需要双向通信,并且需要更高级的功能和更大的灵活性,可以选择WebSocket。


    Learn more:

    1. Server-sent events vs. WebSockets – LogRocket Blog
    2. WebSockets vs Server-Sent Events: Key differences and which to use in 2024
    3. WebSocket vs Server-Sent Events: In-Depth Comparison, Use Cases, Pros & Cons, and Best Practices for Real-Time Communication
人生梦想 - 关注前沿的计算机技术 acejoy.com 🐾 步子哥の博客 🐾 背多分论坛 🐾 借一步网
Page Stats: PV: 230 | UV: 197
Last updated: 2025-05-12 21:35:23
沪ICP备2024052574号-1