---
url: 'https://www.corbado.com/zh/blog/webauthn-server-implementation'
title: '9 个 WebAuthn 服务器实现库比较'
description: '本文帮助您找到合适的 WebAuthn 服务器库以提供通行密钥（passkeys）。我们比较了 9 个库，并提供了寻找合适库的策略。'
lang: 'zh'
author: 'Nicolai'
date: '2026-07-27T08:25:37.919Z'
lastModified: '2026-07-27T08:27:38.401Z'
keywords: 'WebAuthn 服务器实现, WebAuthn 服务器库, 通行密钥, passkeys, 身份验证'
category: 'Passkeys Implementation'
---

# 9 个 WebAuthn 服务器实现库比较

## Key Facts

- **SimpleWebAuthn**（TypeScript，1,000 个 GitHub 星）被评为最直观的，并且独特地为通行密钥实现同时提供服务器库和前端浏览器库。
- 与密码身份验证相比，通行密钥身份验证至少需要**四个后端 API 端点**（密码只需一个），这使得 WebAuthn 服务器库对于处理密码学复杂性变得必不可少。
- **py_webauthn**（Python）非常适合快速测试：只需一次方法调用即可生成身份验证选项，并且不需要框架配置。
- **webauthn-framework**（PHP/Symfony，347 星）提供了最广泛的概念文档，使其成为从零开始学习通行密钥基础知识的开发人员的最佳选择。
- 当没有与您的语言匹配的库时，推荐使用 **go-webauthn** 或 SimpleWebAuthn 作为后备方案，因为它们在商业和开源项目中得到了最广泛的采用。

## 1. 简介：WebAuthn 服务器实现

在 2024 年，提供安全且简单的用户身份验证是数字公司的必备条件。通行密钥（Passkeys）作为新的登录标准，是满足这些需求的理想解决方案。然而，通行密钥为用户带来的增强的用户体验和安全性是有代价的——作为开发人员实现它们时。实现的难度源于通行密钥相对较新（对用户如此，对开发人员亦然），并且与基于密码的身份验证相比，它们的实现可能非常具有挑战性。实际上，通行密钥身份验证至少需要四个 API 端点，而密码身份验证只需要一个 API 端点。

在服务器端提供通行密钥身份验证的核心组件之一是 **WebAuthn 服务器（绿色库部分）**。有关 WebAuthn 服务器如何融入更广泛的企业技术栈集成的全面指南，请参阅我们的专门文章。

![WebAuthn 服务器架构](https://www.corbado.com/website-assets/657d793ffb87095054194ebb_webauthn_server_architecture_e9ba5ad00c.png)_来源：[Yubico](https://developers.yubico.com/java-webauthn-server/)_

在这篇博文中，我们比较了几个 WebAuthn 服务器库/包/SDK，分析了差异，并为刚开始实现通行密钥的开发人员提供了建议。

## 2. 我如何自己实现通行密钥？

为了更好地理解为什么一开始就需要一个 **WebAuthn 服务器库**，让我们看看如何实现通行密钥。原则上，有两种方法可以将通行密钥集成到网站和应用程序中：

1. 使用第三方通行密钥解决方案（例如 Corbado）
2. 使用下面提到的 WebAuthn 服务器库之一自己实现通行密钥

虽然第三方通行密钥解决方案易于集成，通常可以节省大量的工程时间（特别是对于边缘情况、维护、恢复、后备和改善通行密钥用户体验而言），但一些开发人员只是更喜欢自己实现一切。

让我们看看如何自己实现通行密钥（do-it-yourself）。在一个非常基本的设置中，需要一个注册（sign-up）和身份验证（login）的机制。这两个过程，也称为 WebAuthn 仪式（ceremonies），处理方式不同，即使整体流程遵循类似的模式：

1. **前端（浏览器）发起**注册或登录请求，并**调用后端 API** 端点。
2. **后端生成 WebAuthn** 注册或登录**参数**。这些分别被称为 `PublicKeyCredentialCreationOptions` 和 `PublicKeyCredentialRequestOptions`。这些 WebAuthn 参数中最重要的部分之一是 challenge（挑战）。然后，WebAuthn 参数被**发回前端**。
3. **前端**接收这些 WebAuthn 参数并使用它们**验证用户身份**，通过本地设备身份验证系统（例如，通过 Face ID、Touch ID、Windows Hello）。在注册过程中，创建一个新的公私钥对，私钥存储在本地，而公钥发送到服务器。在登录过程中，使用通行密钥的私钥对 **challenge 进行签名**并发送到另一个后端 API 端点。
4. 在注册过程中，后端**接收公钥**并存储它。在登录中，后端**接收签名的 challenge 并验证其完整性**，使用 WebAuthn 服务器。

由于每个注册 / 登录过程都涉及这些步骤，因此后端需要跟踪用户、通行密钥和注册 / 登录请求。

如果您想深入了解通行密钥的工作方式以及简单实现是什么样子（不使用第三方通行密钥解决方案），您可以在[这里](http://ttps://www.corbado.com/blog/passkey-tutorial-how-to-implement-passkeys)阅读我们的博客文章。

在现实生活场景中，当您自己实现通行密钥时，请记住，不仅仅是提供必要的 API 端点和基本实现来注册和登录。最重要的是，您需要解决以下主题和用例：

- 设备管理
- 跨平台和跨设备登录流程
- 用户管理
- 会话管理
- 通行密钥就绪设备检测
- 用户教育
- 后备身份验证选项
- 恢复机制
- 账户共享选项
- 优化通行密钥创建流程和通行密钥登录流程以实现高采用率

尽管如此，对于基本的通行密钥实现，您只需要遵守 WebAuthn 标准。实现一个知名且受支持的 WebAuthn 服务器库通常就足够了。该库生成 WebAuthn 服务器参数并验证登录 challenge，实际上为您接管了密码学和最复杂的部分。

## 3. WebAuthn 服务器后端库：比较

所有被分析的 WebAuthn 服务器库都提供了提供通行密钥身份验证所需的功能。因此，我们特别关注以下标准：

- **身份验证器选择标准（Authenticator Selection Criteria）：** 您如何为特定行为和安全功能（例如强制创建驻留密钥）设置首选项？
- **全局设置（Global Settings）：** 您能在多大程度上集中所需的配置？
- **文档（Documentation）：** WebAuthn 服务器库的文档记录得有多好，是否易于理解
- **示例（Examples）：** 是否有任何示例实现供您参考。

分析了以下 WebAuthn 服务器库（按 2023 年 12 月 GitHub 星数降序排列）：

### 3.1 TypeScript: SimpleWebAuthn

![SimpleWebAuthn](https://www.corbado.com/website-assets/657d796db359dbc15ca87b17_webauthn_server_simplewebauthn_458503b246.png)

- **编程语言：** Typescript
- **框架：** Node.js
- **作者：** Matthew Miller (Duo Security / Cisco)
- **星数：** 1000
- **被使用：** 781
- **贡献者：** 19
- **FIDO 一致性：** 是
- **全局设置：** 否
- **身份验证器选择标准：** 如 [W3C 建议](https://www.w3.org/TR/webauthn-2/#dictionary-authenticatorSelection)（应包含 `authenticatorAttachment`、`residentKey`、`requireResidentKey` 和 `userVerification` 变量，这些也在 W3C 页面上解释了）
- **文档：** 结构良好，专注于快速设置和易用性，包括通行密钥知识，例如解释什么是通行密钥以及它们如何工作
- **示例：** [文档](https://simplewebauthn.dev/docs/advanced/example-project)中提供示例项目
- **推荐数据结构：**

```json
type UserModel = {
  id: string;
  username: string;
  currentChallenge?: string;
};

/**
 * It is strongly advised that authenticators get their own DB
 * table, ideally with a foreign key to a specific UserModel.
 *
 * "SQL" tags below are suggestions for column data types and
 * how best to store data received during registration for use
 * in subsequent authentications.
 */
type Authenticator = {
  // SQL: Encode to base64url then store as `TEXT`. Index this column
  credentialID: Uint8Array;
  // SQL: Store raw bytes as `BYTEA`/`BLOB`/etc...
  credentialPublicKey: Uint8Array;
  // SQL: Consider `BIGINT` since some authenticators return atomic timestamps as counters
  counter: number;
  // SQL: `VARCHAR(32)` or similar, longest possible value is currently 12 characters
  // Ex: 'singleDevice' | 'multiDevice'
  credentialDeviceType: CredentialDeviceType;
  // SQL: `BOOL` or whatever similar type is supported
  credentialBackedUp: boolean;
  // SQL: `VARCHAR(255)` and store string array as a CSV string
  // Ex: ['usb' | 'ble' | 'nfc' | 'internal']
  transports?: AuthenticatorTransport[];
};
```

- **其他特点：** 很棒的 [WebAuthn 响应调试器（WebAuthn Debugger）](https://debugger.simplewebauthn.dev/)，并且不仅提供后端 / 服务器库，还提供前端库（基本上包装了客户端的一些 Web Authentication API）
- **个人评估：** 到目前为止看到的最直观的设置，非常直接。此外，它是少数提供浏览器库以帮助客户端实现的库之一，使其非常出色。该库的作者在 WebAuthn / 通行密钥社区中非常活跃。
- **GitHub 链接：** [https://github.com/MasterKale/SimpleWebAuthn](https://github.com/MasterKale/SimpleWebAuthn)

![SimpleWebAuthn 截图](https://www.corbado.com/website-assets/657d797be263ba3262fff816_webauthn_server_simplewebauthn_screenshot_527317d6be.png)

### 3.2 .NET: fido2-net-lib

![fido2-net-lib](https://www.corbado.com/website-assets/657d79968cef2987ff7c9c21_webauthn_server_fido2_net_lib_6727019f82.png)

- **编程语言：** C#
- **框架：** .NET
- **作者：** Anders Åberg, Alex Seigler
- **星数：** 962
- **被使用：** 200
- **贡献者：** 40
- **FIDO 一致性：** 是
- **全局设置：** 是
- **身份验证器选择标准：** 如 W3C 建议
- **文档：** 只有包含几个示例的 Readme，库的[网站](https://fido2-net-lib.passwordless.dev/)上有一些[通行密钥情报](https://docs.corbado.com/corbado-connect/features/passkey-intelligence)
- **示例：** 提供演示控制器和示例凭证存储以展示示例集成
- **推荐数据结构：**

```json
public class StoredCredential
{
    /// <summary>
    /// The Credential ID of the public key credential source.
    /// </summary>
    public byte[] Id { get; set; }

    /// <summary>
    /// The credential public key of the public key credential source.
    /// </summary>
    public byte[] PublicKey { get; set; }

    /// <summary>
    /// The latest value of the signature counter in the authenticator data from any ceremony using the public key credential source.
    /// </summary>
    public uint SignCount { get; set; }

    /// <summary>
    /// The value returned from getTransports() when the public key credential source was registered.
    /// </summary>
    public AuthenticatorTransport[] Transports { get; set; }

    /// <summary>
    /// The value of the BE flag when the public key credential source was created.
    /// </summary>
    public bool IsBackupEligible { get; set; }

    /// <summary>
    /// The latest value of the BS flag in the authenticator data from any ceremony using the public key credential source.
    /// </summary>
    public bool IsBackedUp { get; set; }

    /// <summary>
    /// The value of the attestationObject attribute when the public key credential source was registered.
    /// Storing this enables the Relying Party to reference the credent’al's attestation statement at a later time.
    /// </summary>
    public byte[] AttestationObject { get; set; }

    /// <summary>
    /// The value of the clientDataJSON attribute when the public key credential source was registered.
    /// Storing this in combination with the above attestationObject item enables the Relying Party to re-verify the attestation signature at a later time.
    /// </summary>
    public byte[] AttestationClientDataJson { get; set; }

    public List<byte[]> DevicePublicKeys { get; set; }

    public byte[] UserId { get; set; }

    public PublicKeyCredentialDescriptor Descriptor { get; set; }

    public byte[] UserHandle { get; set; }

    public string AttestationFormat { get; set; }

    public DateTimeOffset RegDate { get; set; }

    public Guid AaGuid { get; set; }
}
```

- **其他特点：** 被 Bitwarden 使用（初创公司 passwordless.dev 被 Bitwarden 收购）
- **个人评估：** 开发者友好的库，有大量的补充材料
- **GitHub 链接：** [https://github.com/passwordless-lib/fido2-net-lib](https://github.com/passwordless-lib/fido2-net-lib)

![fido2-net-lib 截图](https://www.corbado.com/website-assets/657d79aefc6fa186be1a722e_webauthn_server_fido2_net_lib_screenshot_a624ecd3d2.png)

### 3.3 Python: py_webauthn

![py_webauthn](https://www.corbado.com/website-assets/657d79c9b1ac103f4c903ec1_webauthn_server_py_webauthn_416b6eae90.jpg)

- **编程语言：** Python
- **框架：** 无特定
- **作者：** Duo Labs
- **星数：** 727
- **被使用：** 912
- **贡献者：** 23
- **FIDO 一致性：** N/A
- **全局设置：** 否
- **身份验证器选择标准：** 如 W3C 建议
- **文档：** 很少到没有，需要有先前的通行密钥知识
- **示例：** 包含注册和登录的简短代码示例
- **推荐数据结构：** N/A
- **其他特点：** 需要 Python >= 3.8
- **个人评估：** 文件数量相对紧凑的库，您可以在短时间内获得概览。
- **GitHub 链接：** [https://github.com/duo-labs/py_webauthn](https://github.com/duo-labs/py_webauthn)

![py_webauthn 截图](https://www.corbado.com/website-assets/657d79da1eee1bef26c8ef4b_webauthn_server_py_webauthn_screenshot_5292be32e1.png)

### 3.4 Ruby: webauthn-ruby

![webauthn-ruby](https://www.corbado.com/website-assets/657d79ef3b5153896eb8fd4c_webauthn_server_webauthn_ruby_4fc3b288bd.png)

- **编程语言：** Ruby
- **框架：** Ruby on Rails
- **作者：** Cedarcode
- **星数：** 580
- **被使用：** 679
- **Gem 下载量：** 1800 万
- **贡献者：** 27
- **FIDO 一致性：** 是
- **全局设置：** 是
- **身份验证器选择标准：** 如 W3C 建议
- **文档：** Readme 是文档的唯一来源
- **示例：** N/A
- **推荐数据结构：** N/A
- **其他特点：** 也提供此库的包装器（[warden-webauthn](https://github.com/ruby-passkeys/warden-webauthn), [devise-passkeys](https://github.com/ruby-passkeys/devise-passkeys)）
- **个人评估：** 由于补充材料非常有限，只有在您熟悉 Ruby 和通行密钥的情况下，我们才推荐这个库
- **GitHub 链接：** [https://github.com/cedarcode/webauthn-ruby](https://github.com/cedarcode/webauthn-ruby)

![webauthn-ruby 截图](https://www.corbado.com/website-assets/657d79fd54838aafd2274e4e_webauthn_server_webauthn_ruby_screenshot_7fb391a360.png)

### 3.5 Go: go-webauthn

![go-webauthn](https://www.corbado.com/website-assets/657d7a13b1ac103f4c908c60_webauthn_server_go_webauthn_f4f8db52ec.png)

- **编程语言：** Go
- **框架：** 基于 Go 的框架，如 Gin, Echo ¦
- **作者：** 最初由 Duo Labs 开发 / 由 James Elliott 继续维护
- **星数：** 480
- **被使用：** 280
- **贡献者：** 18
- **FIDO 一致性：** 是
- **全局设置：** 是
- **身份验证器选择标准：** 如 W3C 建议
- **文档：** 带有示例的 Readme 是文档的唯一来源
- **示例：** 提供[示例仓库](https://github.com/ruby-passkeys/devise-passkeys)
- **推荐数据结构：** N/A
- **其他特点：** 文件数量庞大，获得概览需要一些时间
- **个人评估：** 流行的库，一旦您熟悉了它就很容易使用，但是我们建议事先学习一些通行密钥知识（它们是如何工作的，过程是什么样的等）。
- **GitHub 链接：** [https://github.com/go-webauthn/webauthn](https://github.com/go-webauthn/webauthn)

![go-webauthn 截图](https://www.corbado.com/website-assets/657d7a266276ea8bd12bb480_webauthn_server_go_webauthn_screenshot_4bf908cdfd.png)

### 3.6 Java: java-webauthn-server

![java-webauthn-server](https://www.corbado.com/website-assets/657d7a49ac1b2446296c4e2b_webauthn_server_java_webauthn_server_368503276e.png)

- **编程语言：** Java
- **框架：** Maven / Gradle
- **作者：** Yubico
- **星数：** 391
- **被使用：** N/A
- **贡献者：** 27
- **FIDO 一致性：** N/A
- **全局设置：** 是
- **身份验证器选择标准：** 如 W3C 建议。
- **文档：** Readme 是唯一的文档，但相当详细
- **示例：** N/A
- **推荐数据结构：** N/A
- **其他特点：** 带有一个 Credential Repository 接口，为所需的数据库检索方法提供清晰的指导。
- **个人评估：** 尽管您必须自己管理数据库，但凭证存储库在数据库设计过程中有很大帮助。自然地，Java 实现带来了大量的文件，因为每个属性都需要一个类，这些类通常存储在自己的文件中。这使得获得概览成为一项更耗时的任务。
- **GitHub 链接：** [https://github.com/Yubico/java-webauthn-server](https://github.com/Yubico/java-webauthn-server)

![java-webauthn-server 截图](https://www.corbado.com/website-assets/657d7a5aeac136d96d1bb459_webauthn_server_java_webauthn_server_screenshot_0cc89ca1ab.png)

### 3.7 Rust: webauthn-rs

![webauthn-rs](https://www.corbado.com/website-assets/657d7a6dd61bd50a76f5d9ca_webauthn_server_webauthn_rs_1be32ca83b.png)

- **编程语言：** Rust
- **框架：** 基于 Rust (Rocket, Axum ¦)
- **作者：** Kanidm Identity Management Project
- **星数：** 351
- **被使用：** 617
- **贡献者：** 25
- **FIDO 一致性：** N/A
- **全局设置：** 是
- **身份验证器选择标准：** 配置可能性非常有限。其他库完全按照 W3C 标准实现，展示了更强的可配置性
- **文档：** 存在自动生成的技术文档，但不是很详细
- **示例：** 提供包含 3 种不同 Web 框架示例的[教程仓库](https://github.com/kanidm/webauthn-rs/tree/master/tutorial)
- **推荐数据结构：** N/A
- **其他特点：** 该库已通过 SUSE 产品安全部门执行的安全审计。
- **个人评估：** 由于可配置性和文档有限，只有当您的主要框架是基于 Rust 并且您了解通行密钥的工作原理时，我们才会推荐此库
- **GitHub 链接：** [https://github.com/kanidm/webauthn-rs](https://github.com/kanidm/webauthn-rs)

![webauthn-rs 截图](https://www.corbado.com/website-assets/657d7a7db359dbc15ca91760_webauthn_server_webauthn_rs_screenshot_cc92cc955d.png)

### 3.8 PHP: webauthn-framework

![webauthn-framework](https://www.corbado.com/website-assets/657d7bd762d48bffd4a9b34d_webauthn_server_webauthn_framework_07cf99330e.png)

- **编程语言：** PHP
- **框架：** Symfony
- **作者：** Florent Morselli
- **星数：** 347
- **被使用：** N/A
- **贡献者：** 18
- **FIDO 一致性：** 是
- **全局设置：** 是
- **身份验证器选择标准：** 如 W3C 建议。
- **文档：** 广泛的文档，包括技术细节，但也从头开始解释通行密钥
- **示例：** 提供[示例仓库](https://github.com/web-auth/symfony-webauthn-demo)
- **推荐数据结构：**

```php
<?php

declare(strict_types=1);

namespace App\Entity;

use App\Repository\PublicKeyCredentialSourceRepository;
use DateTimeImmutable;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Uid\AbstractUid;
use Symfony\Component\Uid\Uuid;
use Webauthn\PublicKeyCredentialSource as BasePublicKeyCredentialSource;
use Webauthn\TrustPath\TrustPath;

#[ORM\Table(name: 'pk_credential_sources')]
#[ORM\Entity(repositoryClass: PublicKeyCredentialSourceRepository::class)]
class PublicKeyCredentialSource extends BasePublicKeyCredentialSource
{
    #[ORM\Column(type: Types::DATETIME_IMMUTABLE)]
    public readonly DateTimeImmutable $createdAt;

    #[ORM\Id]
    #[ORM\Column(type: Types::STRING, length: 255)]
    #[ORM\GeneratedValue(strategy: 'NONE')]
    private string $id;

    public function __construct(
        string $publicKeyCredentialId,
        string $type,
        array $transports,
        string $attestationType,
        TrustPath $trustPath,
        AbstractUid $aaguid,
        string $credentialPublicKey,
        string $userHandle,
        int $counter
    ) {
        $this->id = Uuid::v4()->toRfc4122();
        $this->createdAt = new DateTimeImmutable();
        parent::__construct($publicKeyCredentialId, $type, $transports, $attestationType, $trustPath, $aaguid, $credentialPublicKey, $userHandle, $counter);
    }

    public function getId(): string
    {
        return $this->id;
    }
}
```

- **其他特点：** N/A
- **个人评估：** 适合想要了解通行密钥但没有先验知识的人
- **GitHub 链接：**[https://github.com/web-auth/webauthn-framework](https://github.com/web-auth/webauthn-framework)

![webauthn-framework 截图](https://www.corbado.com/website-assets/657d7be96276ea8bd12cb5fd_webauthn_server_webauthn_framework_screenshot_9c1e9a3dd8.png)

### 3.9 Java: webauthn4j

![webauthn4j](https://www.corbado.com/website-assets/657d7c00fe6a1b80f0f03fd6_webauthn_server_webauthn4j_d8c4d2a9de.png)

- **编程语言：** Java
- **框架：** Maven
- **作者：** WebAuthn4j
- **星数：** 342
- **被使用：** N/A
- **贡献者：** 19
- **FIDO 一致性：** 是
- **全局设置：** 是
- **身份验证器选择标准：** 与 W3C 建议的带有值 `discouraged`、`preferred`、`required` 的 `UserVerificationRequirement` 参数不同，webauthn4j 提供 `verificationRequired` 和 `userPrecenseRequired` 作为布尔变量
- **文档：** 枯燥，但是提供包含少量代码样本的详尽文档
- **示例：** 提供[示例仓库](https://github.com/webauthn4j/webauthn4j-spring-security)
- **推荐数据结构：** N/A
- **其他特点：** N/A
- **个人评估：** 阅读文档很快会变得乏味和复杂，因为它只是一个专注于功能而非通行密钥背后概念的大页面。
- **GitHub 链接：** [https://github.com/webauthn4j/webauthn4j](https://github.com/webauthn4j/webauthn4j)

![webauthn4j 截图](https://www.corbado.com/website-assets/657d7c7fb359dbc15caa2007_webauthn_server_webauthn4j_screenshot_3d7616a5e5.png)

下表提供了 WebAuthn 服务器库的概述：

![WebAuthn 服务器概述](https://www.corbado.com/website-assets/657d7c8fffd0b1429fd8d276_webauthn_server_implementation_overview_92a55c2e0f.png)

## 4. 建议：驾驭 WebAuthn 库领域

### 4.1 第 1 步：选择您的 WebAuthn 库

由于大多数库同样强大并实现了 WebAuthn 标准，我们建议采用以下决策树：

- **提供您的框架和编程语言的 WebAuthn 服务器库：** 我们没有列出依赖于上述库之一的框架库（例如，有可用于 Symfony 和 Laravel 的 PHP 定制版）。如果有框架实现，请选择此实现，因为它允许您将 WebAuthn API 调用原生实现到您当前的框架结构中，并使用您的数据库抽象来实现存储。
- **提供您的编程语言的 WebAuthn 服务器库：** 由于您需要后端 API 端点，请选择您原生编程语言的 WebAuthn 服务器库，以便它可以原生嵌入到您当前的 API 端点中。
- **没有提供您编程语言的 WebAuthn 服务器库：** 在这种情况下，您应该考虑使用像 Corbado 这样的托管通行密钥解决方案。如果这不可行，我们建议使用 `go-webauthn` 或 `SimpleWebAuthn`，因为它们的采用率最高、轻量级，并且也被许多商业和开源项目使用。

如果您只是想总体上了解有关 WebAuthn 服务器的更多信息，而尚未有一个具体的项目，我们可以提出一些建议，因为这些库及其补充材料（如文档和示例实现）之间存在一些差异。因此，对于渴望开启通行密钥实现之旅的软件开发人员，我们建议选择以下实现：

- **对于快速测试：** `py_webauthn` 包提供了即时实现和现成可用的[代码片段](https://github.com/duo-labs/py_webauthn/blob/master/examples/registration.py)。只需一次方法调用，您就可以生成身份验证所需的选项。由于您不需要将库嵌入框架并配置它，因此它非常适合快速测试。
- **对于直观的实现：** 用 Typescript 编写的 `SimpleWebauthn` 包非常简单且对开发者友好。像 `py_webauthn` 一样，实现非常极简，但它还附带指导您完成身份验证过程的文档。然而，与 `py_webauthn` 相比，`SimpleWebAuthn` 没有带有一个无需修改即可运行的清晰示例。
- **对于深入理解：** PHP 的 `webauthn-framework` 库以专注于通行密钥概念的广泛、结构化[文档](http://Link)脱颖而出。与具有大量文档的其他库（如 `webauthn4j`）的主要区别在于文档的设计和生动性。

如果想更深入地了解 WebAuthn 在服务器端是如何工作的，您可以阅读 WebAuthn RFC 中非常详细的“WebAuthn 信赖方操作（WebAuthn Relying Party Operations）”部分，其中详细说明了[注册新凭据 (7.1)](https://www.w3.org/TR/webauthn-2/#sctn-registering-a-new-credential)和[验证身份验证断言 (7.2)](https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion)所需实现的每个步骤。

### 4.2 第 2 步：定义您的 WebAuthn 服务器选项

评估您具有的特定通行密钥和 WebAuthn 需求。在这篇博文中，我们假设您只想支持通行密钥作为可发现凭据（discoverable credentials）。阅读有关 `PublicKeyCredentialCreationOptions` 和 `PublicKeyCredentialRequestOptions` 的信息，结合客户端的 `navigator.credentials.create()` 和 `navigator.credentials.get()` WebAuthn API 调用，在 WebAuthn 服务器 SDK 配置中为您的用例正确设置参数。

### 4.3 第 3 步：定义数据库结构

对于所有的 WebAuthn 服务器库，您都需要提供适当的数据库结构来持久化 / 访问以下信息：

- 凭证 (Credentials)
- 用户 (Users)
- 挑战 (Challenges)
- 身份验证器 (Authenticators)

对于某些库，有具体的建议和示例（如果我们认为它们有用，我们已在上面提供）。彻底了解需要将哪些 WebAuthn 字段存储在何处至关重要。特别注意识别您要用于用户 ID（`user.id`）的值。我们在这里有更详细的解释。还要考虑当用户可能删除通行密钥时会发生什么。除此之外，您可以选择性地限制某些身份验证器的使用。可以在[此处](https://github.com/passkeydeveloper/passkey-authenticator-aaguids)找到与通行密钥相关的有效身份验证器列表。如果您还想支持并检查安全密钥（security keys）的证明（attestations），这完全是另一回事了。您可以在[此处](https://fidoalliance.org/metadata/)找到更多信息。

### 4.4 第 4 步：在您的用户设备上测试

识别您的用户将在哪些设备上使用通行密钥和后备身份验证方法。如果您不确定您的用户使用哪些设备、浏览器和操作系统，请查看 [State of Passkeys](https://state-of-passkeys.io/) 获取跨平台、浏览器和操作系统的最新通行密钥就绪情况数据。如果您对某些设备的通行密钥采用率和通行密钥就绪份额有具体问题，请随时联系我们。我们很乐意为您提供进一步的见解，并在此主题上帮助您（另请参阅我们关于通行密钥就绪情况的最新博文）。从可观测性的角度来看，将客户端 WebAuthn 故障和服务器验证拒绝作为不同的数据流保留；对于客户端存储桶（bucket）定义，请使用 WebAuthn 错误。此外，您应该记住，对于 Windows 10 和 Linux，您需要提出专门的解决方案，因为这些操作系统提供的通行密钥支持最少（如果有的话）。

## 5. 结论

目前几乎对于所有语言或框架都有一个成熟的 WebAuthn 服务器库。比较不同语言的库并没有显示出某些实现的明显优势。相反，您应该使用您最熟悉的框架 / 编程语言。或者，如果您不想自己实现 WebAuthn 并处理所有随之而来的麻烦，您可以尝试像 Corbado 这样专门的、预构建的通行密钥身份验证解决方案。作为一个以通行密钥为中心的一体化身份验证解决方案，它带有很棒的[通行密钥情报](https://docs.corbado.com/corbado-connect/features/passkey-intelligence)、会话管理以及后备身份验证方法，因此您可以专注于开发您的产品，而无需担心身份验证。您可以[在此](https://app.corbado.com/signin#register)注册不限用户数的免费试用。

## 常见问题解答

### 我如何为我的项目选择合适的 WebAuthn 服务器库？

首先检查是否存在适用于您特定框架的库，然后是适用于您的编程语言的库。由于所有列出的库都同等地实现了 WebAuthn 标准，选择应该优先考虑对您现有技术栈的熟悉程度，而不是库之间的功能差异。

### 在构建 WebAuthn 服务器时，我需要在数据库中存储哪些数据？

至少必须持久化凭证、用户、挑战和身份验证器。密切注意您分配为用户 ID（userHandle）的值，并为用户可能从其设备中删除通行密钥的情况做好计划。

### 为什么我不能在不使用库的情况下从头开始实现 WebAuthn 服务器端验证？

WebAuthn 服务器库处理最复杂的密码学操作：生成 PublicKeyCredentialCreationOptions 和 PublicKeyCredentialRequestOptions 参数以及验证签名的挑战。从头开始正确地执行此操作比使用已经过测试和审计的符合 FIDO 标准的库要困难得多。

### 哪些操作系统的通行密钥支持最差，并且需要在 WebAuthn 实现中进行额外处理？

Windows 10 和 Linux 提供的通行密钥支持最少，因此需要为这些平台上的用户提供专用的后备解决方案。将客户端 WebAuthn 故障和服务器验证拒绝作为独立的流进行监控，有助于在生产环境中识别特定于操作系统的问题。
