本文讲解如何在原生应用(iOS + Android)中实现 Passkey。您将了解到哪种类型的 WebView 最适合用于 Passkey 认证。

Vincent
Created: June 20, 2025
Updated: December 10, 2025

Passkeys Series: Native Apps
See the original blog version in English here.
+70-page Enterprise Passkey Whitepaper:
Learn how leaders get +80% passkey adoption. Trusted by Rakuten, Klarna & Oracle
| 方法 | 采用率 | 创建 Passkey | 使用 Passkey | 管理 Passkey | 技术复杂度 | OAuth 支持 |
|---|---|---|---|---|---|---|
| 原生实现 | 🟢🟢🟢 | 采用率高,最佳 UX,无缝生物识别 | 即时、静默认证 | 完全原生控制 | 中-高 | 需要独立流程 |
| 系统 WebView | 🟢🟢 | 采用率良好,类似浏览器的体验 | 标准浏览器 UX,共享密钥链 | 基于浏览器的管理 | 低 | 极佳 |
| 嵌入式 WebView | 🟢 | 采用率较低,需要更多设置 | iOS 和 Android 原生支持(WebKit 1.12.1+),无 Conditional UI | 有限的控制 | 中-高 | 不适用 |
注意: 系统 WebView 和嵌入式 WebView 常常结合使用。系统 WebView 负责处理登录(自动共享凭据),然后嵌入式 WebView 在设置中渲染 Passkey 管理界面。
关键决策因素:
现代移动平台为原生应用提供了三种不同的 Passkey 集成方法,每种方法在用户体验、技术复杂度和 OAuth 兼容性方面都有不同的权衡:
原生实现:使用平台 API(iOS 的 AuthenticationServices,Android 的 Credential Manager)直接在应用中构建 Passkey 流程。这种方法能提供最佳的用户体验,实现无缝的生物识别认证,但技术实现工作量为中到高。
系统 WebView:使用平台的浏览器组件(iOS 的 ASWebAuthenticationSession / SFSafariViewController,Android 的 Chrome Custom Tabs)来处理认证。这种方法非常适合基于 OAuth 的登录流程,并能与系统浏览器共享凭据。
嵌入式 WebView:在应用内嵌入一个可定制的网页视图(iOS 的 WKWebView,Android 的 WebView),以便在原生应用骨架中复用网页认证。它能提供类似原生的外观,没有 URL 地址栏,并且可以完全控制 WebView 的 UI。但这需要额外的设置,包括权限和授权(iOS),以及使用 AndroidX WebKit 1.12.1+ 配置 WebView(Android),才能启用 Passkey 功能。
正确的选择取决于您应用的认证架构、是否使用 OAuth 提供商、对 UI 的控制需求,以及您是在构建原生优先的应用还是在复用网页组件。
原生 Passkey 实现能提供最优的用户体验,认证流程使用平台特定的 API 直接构建在应用 UI 中。用户可以享受到平台原生的对话框、无缝的生物识别验证和最快的登录速度。
何时选择原生实现:
preferImmediatelyAvailableCredentials
在有可用 Passkey 时自动显示 Passkey 浮层,无需输入标识符,提供最快的登录体验关键优势:preferImmediatelyAvailableCredentials()
原生实现可以利用 preferImmediatelyAvailableCredentials()
创建一个自动 Passkey 浮层,当有可用 Passkey 时,这个浮层会在应用启动时立即出现。这种无用户名的流程提供了最快的登录体验——用户无需先输入标识符就能立即看到他们的 Passkey。这个功能是原生实现独有的,在 WebView 方案中无法使用。
虽然 WebView 实现可以使用 Conditional UI(在输入框中提供 Passkey 建议),但原生实现的自动浮层提供了更优的 UX,因为认证在应用启动时就立即开始,从而带来更高的 Passkey 使用率。
技术要求概述:
原生 Passkey 集成要求您的应用和 Web 域之间建立加密信任关系。否则,操作系统将拒绝所有 WebAuthn 操作。关键要求包括:
/.well-known/ 下的应用-域关联文件主要的好处是:在您的网站上创建的 Passkey 可以在您的应用中无缝使用,反之亦然。
在 iOS 上原生实现 Passkey 需要使用苹果的 AuthenticationServices 框架,该框架为 WebAuthn 操作提供了 API:
关键组件:
ASAuthorizationController:管理认证流程ASAuthorizationPlatformPublicKeyCredentialProvider:创建 Passkey 请求开发技巧
?mode=developer 以强制刷新。Android 的原生 Passkey 实现使用 Credential Manager API(或旧版的 FIDO2 API 以实现向后兼容):
关键组件:
CredentialManager:所有凭据操作的中心 APICreatePublicKeyCredentialRequest:用于 Passkey 注册GetCredentialRequest:用于 Passkey 认证注意:Android 目前在原生应用中缺少像 iOS 那样的 Conditional UI 键盘建议(尽管 Conditional UI 在 Web 应用中是可用的)。
原生实现 Passkey 会遇到一些重要的挑战和经验教训:在操作系统层面进行集成,可能会暴露出不同设备和操作系统版本之间的问题。
虽然您可以使用原始的平台 API 来实现 Passkey,但专用的 SDK 能通过处理 WebAuthn 的复杂性、边缘情况并提供内置的遥测数据,从而显著加快开发速度。SDK 还为单元测试提供了可模拟的接口(这至关重要,因为您无法在模拟器中测试生物识别)。
建议: 对于原生实现,我们推荐使用 Corbado SDK(iOS Swift Passkey SDK、Android Kotlin Passkey SDK),它们处理了在生产部署中发现的大量边缘案例,并提供了额外的遥测和测试功能。
Igor Gjorgjioski
Head of Digital Channels & Platform Enablement, VicRoads
Corbado proved to be a trusted partner. Their hands-on, 24/7 support and on-site assistance enabled a seamless integration into VicRoads' complex systems, offering passkeys to 5 million users.
快速实现数百万用户采用的 Passkey。从 Corbado 的采用平台开始。
开始免费试用系统 WebView 使用平台的原生浏览器组件来处理应用内的认证。与完全原生的实现不同,系统 WebView 使用实际的系统浏览器(iOS 上的 Safari,Android 上的 Chrome)来显示网页内容,从而保留了共享的 cookie、已保存的凭据以及用户熟悉的浏览器安全指示器。
何时选择系统 WebView:
主要优势:
平台组件:
ASWebAuthenticationSession(推荐用于认证流程)或
SFSafariViewController(用于通用浏览)。像 Google 和 GitHub 这样的大公司都采用了这种方法,通过在现有的 Web 认证页面上叠加 WebView,为其移动应用添加 Passkey 登录功能。当无法立即进行完全原生的认证重构时,这种方法非常有效。
iOS 为认证提供了两种主要的系统 WebView 组件:
ASWebAuthenticationSession(推荐用于认证):
SFSafariViewController(通用浏览):
| 功能 | ASWebAuthenticationSession | SFSafariViewController |
|---|---|---|
| 主要用例 | 认证流程 | 通用网页浏览 |
| OAuth/OIDC | 极佳 | 良好 |
| Passkey 支持 | 是 | 是 |
| 定制化 | 有限 | 极少 |
如果您的应用使用基于 OAuth 的登录,推荐选择
ASWebAuthenticationSession,因为它专为认证场景设计,并能在安全性和用户体验之间取得最佳平衡。
Chrome Custom Tabs (CCT) 在您的应用内提供由 Chrome 驱动的认证体验:
主要特性:
OAuth 集成:Chrome Custom Tabs 是 iOS ASWebAuthenticationSession 在 Android 上的等价物,提供出色的 OAuth 支持,同时保留对已存储 Passkey 的访问权限。
嵌入式 WebView 让您可以完全控制应用内网页内容的渲染,允许直接操作 cookie、会话和导航,且不显示 URL 栏。然而,这种控制权需要额外的技术配置才能启用 Passkey 功能。
何时选择嵌入式 WebView:
重要背景:
许多应用采用混合方法:使用系统 WebView 处理初始的 OAuth 认证(Passkey 在此能无缝工作),然后在认证后切换到嵌入式 WebView,以便在设置中管理 Passkey。挑战在于尝试直接在嵌入式 WebView 中使用 Passkey。
技术要求:
与系统 WebView 相比,嵌入式 WebView 需要额外的设置:
平台组件:
WKWebViewandroid.webkit.WebView权衡:
当通过 WebView 实现 Passkey 时,理解系统 WebView 和嵌入式 WebView 之间的区别至关重要。上面概述的三种方法(原生实现、系统 WebView 和嵌入式 WebView)各自服务于不同的用例。
在 iOS 上,您有多种在应用内显示 Web 内容的选项:
在 Android 上,主要的选择是:
android.webkit.WebView),它本质上是一个可以嵌入到您的 Activity 中的迷你浏览器。它高度可定制,但在您的应用进程中运行。在接下来的部分中,我们将更深入地探讨 iOS 和 Android 的这些 WebView 类型,并讨论哪种最适合 Passkey 认证流程。
苹果平台提供了上述三种 WebView 选项。您的选择将影响 Passkey 在应用内的使用流畅度:
要测试 iOS 中不同 WebView 的行为,我们推荐使用这款应用:WebView - WKWebView and UIWebView rendering。
WKWebView 是 iOS 的一个多功能 WebView 组件。开发者可以嵌入一个 WKWebView 来渲染 Web 内容,并对其 UI 和行为有很高的控制度。WKWebView 使用与 Safari 相同的渲染引擎,因此性能非常好,并支持现代 Web 功能。理论上,如果配置正确,WKWebView 可以处理 WebAuthn(从而支持 Passkey),但请注意,出于安全原因,某些高级浏览器功能可能会受到限制。需要注意的一点是,WKWebView 默认不与移动版 Safari 共享 cookie 或钥匙串数据。用户可能需要重新登录,因为他们的 WebView 会话与 Safari 的会话是隔离的。此外,由于 WKWebView 的内容可以由应用完全定制,用户看不到地址栏或 Safari UI——这对于品牌塑造来说很棒,但意味着用户几乎没有线索来验证页面的合法性(这是一个反钓鱼的担忧)。一些应用甚至滥用 WKWebView 来注入脚本或篡改内容(例如,TikTok 就被发现在其应用内浏览器中通过 WKWebView 注入跟踪 JS),因此必须谨慎使用 WKWebView,确保其安全且值得用户信赖。
SFSafariViewController 提供应用内的 Safari 体验。当您使用 SFSafariViewController 打开一个 URL 时,几乎就像在真正的 Safari 浏览器中打开它一样,只是用户仍然停留在您的应用 UI 内。这对 Passkey 的好处是显著的:因为它本质上是 Safari,所以用户的 iCloud Keychain 和已保存的 Passkey 都可以访问。请注意,在 iOS 11+ 上不共享 cookie。这意味着如果用户已经为您的网站创建了 Passkey,Safari 可以找到它,甚至显示 Conditional UI 自动完成功能以便轻松登录。SFSafariViewController 的可定制性较低(您不能大幅更改其工具栏),但它会自动处理许多安全和隐私功能。URL 栏会显示,并带有 HTTPS 的挂锁图标,这让用户确信他们访问的是正确的域名。总的来说,SFSafariViewController 被认为比原始的 WKWebView 更安全,并且实现起来更简单(苹果将其作为即插即用的组件提供)。主要的权衡是您牺牲了对外观和感觉的一些控制。对于认证流程来说,这通常是可以接受的。这里的优先事项是安全性和登录的便捷性,而 SFSafariViewController 通过使用 Safari 的上下文在这方面表现出色。
| WKWebView | SFSafariViewController | |
|---|---|---|
| 用户体验 | - 原生感: 用户可能会觉得网页内容是应用的原生部分,因为开发者可以定制外观和感觉以匹配应用的设计。 - 自动填充: 可以使用来自 Safari 的数据进行自动填充。 | - 无缝体验: 使用用户的 Safari 设置,确保原生应用和浏览器之间的网页浏览体验一致,提供无缝的用户体验。 |
| 开发者体验 | - 高度可定制: 提供广泛的定制和配置选项。 - 灵活: 提供许多用于与网页内容交互的 API。 | - 中度可定制: 定制选项有限,特别是与 WKWebView 相比。 - 简单: 与 WKWebView 相比,实现更简单。 |
| 性能 | - 相对较慢: 根据实现和网页内容的不同,加载速度可以优化,但由于需要额外处理自定义功能和交互,可能仍比 SFSafariViewController 慢。 | - 相对较快: 通常性能更好,因为它利用了为速度和效率优化的 Safari 引擎,为网页提供了快速的加载时间。 |
| 信任与识别 | - 不要求显示 URL: WKWebView 通常不显示 URL,使用户更难验证网页。恶意应用可能会模仿这种行为并进行钓鱼攻击。 | - 类似浏览器的体验: 使用 Safari 渲染网页,提供“类似浏览器”的体验。用户可以看到 URL 并访问 Safari 的自动填充功能,熟悉的界面可能会带来更多信任。 |
| 隔离性 | - 分离: Cookie 和会话与 Safari 分离;用户不会在 WKWebView 中自动登录。 | - 分离: Cookie 和会话也与 Safari 分离;用户同样不会在 SFSafariViewController 中自动登录。 |
| 漏洞 | - 安全: 由于苹果的应用沙盒机制,本身是安全的,但其行为和安全性取决于应用的实现。如果实现不当,可能存在漏洞。 | - 更安全: 受益于 Safari 内置的安全功能,包括反钓鱼和恶意网站警告。由于这些功能和用户对 Safari 的熟悉度,通常认为它在显示网页内容方面比 WKWebView 更安全。 |
| 其他 | - 部分功能不可用: 由于安全问题和 WKWebView 在应用上下文中运行,某些浏览器功能(例如 WebAuthn)可能无法完全访问。 - JavaScript 注入: 一些应用,如 TikTok,会在其应用内的 WKWebView 中注入跟踪 JavaScript,或限制用户控制(如 Facebook)。 - 隐私问题: 有更多关于隐私的社区反馈。 | - 无 JavaScript 注入: 不允许应用执行 JavaScript,增强了安全性和隐私。它也不支持 JavaScript 警报或确认框,这可能会影响某些网页的用户体验。 - 阅读模式: 提供阅读模式,为文章提供干净、易于阅读的版本。 |
SFAuthenticationSession / ASWebAuthenticationSession —— 这些类(后者是更新的、对 Swift 更友好的名称)是专门为像 OAuth 或 OpenID Connect 这样的登录流程构建的。当您需要通过网页对用户进行身份验证时(可能需要访问外部 IdP),这些会话是 iOS 上的推荐选择。它们与 SFSafariViewController 非常相似,因为它们在底层利用 Safari 浏览器并与 Safari 共享 cookie/存储。关键区别在于,SFAuthenticationSession 总是会提示用户应用希望使用网页进行身份验证(以提高用户意识),并且如果可用,它会自动使用用户现有的 Safari 会话。
这样做的好处是实现了无缝的 SSO 体验——如果用户已经在 Safari 中登录了提供商,此会话可以使用该 cookie 来避免再次登录。对于 Passkey 来说,这一点很重要,因为它意味着存储在 Safari/iCloud Keychain 中的任何 Passkey 凭据也可以在这里使用。苹果的官方指南建议对任何看起来像登录流程的操作都使用 ASWebAuthenticationSession。其优点是增强了隐私性(您的应用永远看不到凭据或 cookie,由 Safari 处理)和内置的 SSO 支持。缺点是它仅限于认证流程(您不会用它来在应用中渲染任意的网页内容)。总而言之,如果您在 iOS 上选择 WebView 方法,ASWebAuthenticationSession 通常是实现 Passkey 的最佳选择,因为它安全、与 Safari 共享状态,并且是为认证而专门设计的。
在 Android 上,WebView 的决策是在经典的 WebView 和 Chrome Custom Tabs 之间选择:
要测试 Android 中不同 WebView 的行为,我们推荐使用这款应用:WebView vs Chrome Custom Tabs。
Android WebView (android.webkit.WebView) 是一个允许您在 Activity 布局中嵌入网页的组件。它与 WKWebView 类似,因为它给了您完全的控制权:您可以拦截导航、注入 JavaScript、定制 UI 等。它也在您的应用进程内运行。使用 WebView 实现 Passkey 意味着您的应用加载您的 Web 登录页面,该页面可以启动 WebAuthn Passkey 流程。现代的 Android WebView 支持 WebAuthn(前提是设备的 WebView 实现通过 Android System WebView 或 Chrome 组件保持最新)。一个主要考虑因素是:默认情况下,Android WebView 不与用户的 Chrome 浏览器共享 cookie 或存储的凭据。因此,在 WebView 中创建或使用的任何 Passkey 可能不为 Chrome 所知,反之亦然。这种隔离对安全有好处(您的应用无法读取浏览器 cookie),但如果用户已经在 Chrome 中进行了身份验证,这可能会迫使用户再次登录。另一个问题是信任。一个普通的 WebView 不会显示 URL 或 SSL 锁图标,所以用户必须完全信任您的应用不会对他们进行钓鱼攻击。由于潜在的钓鱼风险,Google 甚至禁止使用 WebView 进行 Google OAuth 登录。在性能方面,WebView 还可以,但它们可能比使用用户的默认浏览器更慢或更耗内存,尤其是在加载大型页面时。
Chrome Custom Tabs (CCT) 是一种混合方法。它们允许您的应用打开一个由 Chrome 渲染的页面,看起来就像是您应用的一部分。您可以定制工具栏颜色、添加应用徽标等,但内容由 Chrome 在一个单独的进程中渲染。对于 Passkey,CCT 有几个好处:它们与 Chrome 共享用户的 cookie 和凭据,这意味着如果用户通过 Chrome(Google 密码管理器)保存了 Passkey,Custom Tab 可以访问它。用户还会看到实际的 URL 和安全指示器,这有助于建立信任。性能通常更好——Chrome 可以在后台“预热”以加快加载速度。而且重要的是,安全性很强:因为它本质上是 Chrome 应用,所以像 Google Safe Browsing 这样的功能会保护会话,并且您的应用无法向页面注入任意脚本(防止某些攻击)。
缺点是它要求用户安装并更新 Chrome(或受支持的浏览器)。大多数 Android 用户都有,但在某些地区的一些设备上,这可能是一个问题。总的来说,如果您在 Android 上采用嵌入式 Web 方法,Chrome Custom Tabs 是 Passkey 流程的推荐选择,因为它们在集成和安全性之间取得了很好的平衡。实际上,它们在很多方面都类似于 iOS 的 SFSafariViewController/ASWebAuthSession——利用默认浏览器进行认证。
(旁注:苹果的 WKWebView vs SFSafariViewController 和 Android 的 WebView vs CCT 有许多相似之处。Safari VC 和 Chrome Tabs 都共享浏览器状态并提供更好的安全性,而 WKWebView/Android WebView 则提供更多控制权但隔离了 Web 内容。对于 Passkey,共享状态(cookie、凭据存储)通常是可取的,这样可以无缝地访问和创建 Passkey。)
| 功能 | WebView | Chrome Custom Tab |
|---|---|---|
| 用户体验 | - 灵活性: 提供丰富的 API 用于与网页内容交互和管理用户交互,包括处理 JavaScript 对话框和权限请求。 - 一致性: 保持一致的 UX,尤其是在处理各种网页内容时,可能具有挑战性。 | - 浏览器功能: 共享数据节省和跨设备同步自动完成等功能。 - 返回按钮: 允许用户通过集成的返回按钮轻松返回应用。 - 依赖性: 依赖 Chrome 应用,该应用可能在所有用户设备上都不可用或未更新。 - 重定向到浏览器: 某些功能可能会将用户重定向到 Chrome 应用,可能中断用户体验。 - 部分 Custom Tabs: 只有屏幕的一部分可用于 Chrome Custom Tab,其余部分显示原生应用。 - 侧边栏: 在横屏模式和或大屏设备上,Chrome Custom Tab 仅显示在屏幕的一侧,其余部分显示原生应用。 |
| 开发者体验 | - 高度可定制: 提供广泛的定制选项/需求。 - 交互性: 提供众多 API 用于与网页内容交互和管理用户交互。 | - 可定制: 允许定制工具栏颜色、操作按钮、底部工具栏、自定义菜单项以及进出动画。 - 回调: 在发生外部导航时向应用程序发送回调。 - 安全功能: 提供开箱即用的功能,无需管理请求、权限授予或 cookie 存储。 |
| 性能 | - 中等性能: 可能无法提供与 Chrome Custom Tabs (CCT) 相同的性能水平。 | - 预热: 包括在后台预热浏览器和推测性加载 URL,以缩短页面加载时间。 - 优先级: 通过将其重要性提升到“前台”级别,防止启动 Custom Tab 的应用在使用期间被系统回收。 |
| 信任与识别 | - URL 和 SSL 不可见: 在 WebView 中,URL 和 SSL 信息本身是不可见的。除非应用开发者实现这些功能,否则用户无法知道他们是在正确的网站上还是在钓鱼网站上。 | - URL 和 SSL 可见: 使用实际的 Chrome 浏览器渲染页面。用户可以看到 URL 和 SSL 证书(指示连接是否安全)。这可以给用户信心,让他们相信自己不在钓鱼网站上。 |
| 隔离性 | - 在应用的进程内运行: 如果应用存在允许恶意代码执行的漏洞,则存在 WebView 可能被攻破的风险。然而,WebView 也会收到更新,但其行为和安全性更依赖于使用它的应用。 - 无 Cookie/会话共享: 不与设备的主浏览器共享 cookie 或会话,提供了隔离性,但可能需要用户重新登录。 | - 在 Chrome 的进程内运行: 作为 Chrome 的一部分,Custom Tabs 在同一进程中运行,并具有与 Chrome 相同的安全更新和功能。 - 共享的 Cookie Jar 和权限模型: 确保用户不必重新登录网站或重新授予权限。 - Chrome 设置与偏好: 利用 Chrome 的设置和偏好。 |
| 漏洞 | - 回调窃取凭据: 潜在漏洞包括有时需要 JavaScript,这为其他应用运行恶意代码打开了大门,例如注册试图拦截用户名和密码的回调。 - 钓鱼: 此外,恶意应用可能会打开一个模仿 Link 流程的另一个网页,以进行钓鱼攻击。 | - Google 安全浏览: 采用 Google 的安全浏览功能,保护用户和设备免受危险网站的侵害。 - 安全的浏览器装饰: 确保用户始终能看到他们正在交互的确切 URL,并可以查看网站的证书信息,从而降低钓鱼风险。此外,Custom Tabs 不允许 JavaScript 注入。 |
| 其他 | - Google 禁止使用 WebView 让用户登录 Google 账户。 |
无论您选择哪种实现方法,都必须满足某些技术要求才能启用 Passkey 功能。本节提供了有关配置 well-known 关联文件、iOS entitlements 和 Android WebView 配置的全面指南。
关于受管设备的说明: 在受移动设备管理(MDM)策略控制凭据存储的受管设备上,Passkey 的行为会有显著不同。有关在受管设备上测试 Passkey 的信息,请参阅在受管 iOS 和 Android 设备上测试 Passkey。
原生和嵌入式 WebView 流程需要关联文件来在您的应用和 Web 域之间建立加密信任。系统 WebView(ASWebAuthenticationSession)和 Chrome Custom Tabs 不需要应用到站点的关联。
AASA 文件建立了您的 iOS 应用和您的 Web 域之间的连接,使 Passkey 能够跨两个平台工作。
文件位置:https://yourdomain.com/.well-known/apple-app-site-association
配置要求:
/.well-known/apple-app-site-association 路径下。application/json。.well-known 路径上无重定向。AASA 文件示例:
{ "webcredentials": { "apps": ["TEAMID123.com.example.app"] } }
AASA 缓存和测试:
苹果会积极地缓存 AASA 文件(长达 24-48 小时),这可能会给开发和测试带来麻烦。要在开发期间绕过缓存:
?mode=developer。⚠️ 重要提示:不要在生产版本中使用
?mode=developer。此参数仅用于开发——在生产环境中使用它会阻止 iOS 正确检测您的 AASA 文件,从而破坏 Passkey 功能。
验证:使用苹果的 AASA 验证器来验证您的配置。
Android 使用 Digital Asset Links 来验证您的应用和网站之间的关系。
文件位置:https://yourdomain.com/.well-known/assetlinks.json
配置要求:
/.well-known/assetlinks.json 路径下。application/json。assetlinks.json 文件示例:
[ { "relation": [ "delegate_permission/common.handle_all_urls", "delegate_permission/common.get_login_creds" ], "target": { "namespace": "android_app", "package_name": "com.example.app", "sha256_cert_fingerprints": [ "AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99:AA:BB:CC:DD:EE:FF:00:11:22:33:44:55:66:77:88:99" ] } } ]
验证:使用 Google 的 Digital Asset Links 生成器来创建和验证您的配置。
iOS 应用需要适当的授权才能访问 Passkey 功能。根据您的实现方法,要求略有不同。
授权文件(在 Flutter 应用中通常命名为
Runner.entitlements,在原生 iOS 项目中为
YourApp.entitlements)定义了苹果系统授予的特殊权限和能力。对于 Passkey,此文件配置了关联域(Associated
Domains)。
文件位置:通常在您的 Xcode 项目的 ios/Runner/Runner.entitlements 中。
原生实现和嵌入式 WebView 需要关联域能力来将您的应用与您的 Web 域链接起来。系统 WebView (ASWebAuthenticationSession) 不需要此项,因为它在 Safari 的上下文中运行。
在 Xcode 中设置:
webcredentials: 前缀。配置示例:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.developer.associated-domains</key> <array> <string>webcredentials:yourdomain.com</string> <string>webcredentials:subdomain.yourdomain.com</string> </array> </dict> </plist>
| 方法 | 是否需要关联域 | 额外配置 |
|---|---|---|
| 原生实现 | 是 | 专门的实现 |
| 系统 WebView | 不需要 | 默认的网页设置即可 |
| 嵌入式 WebView | 是 | 需要 AndroidX WebKit 1.12.1+ 配置 |
多个域:如果您的应用需要与多个域协同工作,您可能需要相关源请求 (ROR)。
Android 嵌入式 WebView 在 AndroidX WebKit 1.12 中获得了原生的 WebAuthn 支持,从而不再需要自定义的 JavaScript 桥接代码。系统 WebView(Chrome Custom Tabs)不需要任何配置——凭据会自动工作。
要求:
实现:
import androidx.webkit.WebSettingsCompat import androidx.webkit.WebViewFeature // 检查是否支持 Web Authentication if (WebViewFeature.isFeatureSupported(WebViewFeature.WEB_AUTHENTICATION)) { // 启用 Web Authentication WebSettingsCompat.setWebAuthenticationSupport( webView.settings, WebSettingsCompat.WEB_AUTHENTICATION_SUPPORT_FOR_APP ) // 启用 JavaScript webView.settings.javaScriptEnabled = true }
关键点:
WebViewFeature.WEB_AUTHENTICATION。mediation:"conditional"(输入字段中的 Passkey 自动填充)在嵌入式 WebView 中不起作用。版本说明:
在 AndroidX WebKit 1.12.0 之前,嵌入式 WebView 中不存在原生 WebAuthn 支持。团队必须选择:
如果您需要支持较旧的 Android 版本或没有更新 WebView APK 的设备,请参阅 Android 的 Credential Manager WebView 集成指南了解桥接代码方法。但是,我们强烈建议现代应用使用原生的 WebKit 1.12.1+ 方法。
建议:使用 AndroidX WebKit 1.12.1+ 的原生 WebAuthn 支持。如果运行时不可用,则回退到 Chrome Custom Tabs,它提供了出色的 Passkey 支持和共享凭据。
在原生应用中实现 Passkey 时,您需要在您的应用和一个或多个 Web 域之间建立信任。本节介绍如何处理单个域、多个相关域(ROR)以及如何验证您的 well-known 关联文件是否配置正确。
对于使用单个域的应用(例如 kayak.com),您需要:
webcredentials:kayak.com 的关联域授权相关源 (ROR)
是 WebAuthn 的一项功能,允许一组 Passkey 在多个相关域(例如
kayak.com、kayak.de、kayak.co.uk)之间工作。ROR
使用每个站点上的 /.well-known/webauthn
端点来定义相关源,而不是使用 AASA 或 assetlinks 文件。
关键点:
/.well-known/webauthn
文件,其中包含相关源的列表。配置示例:
如果您的应用与 kayak.com 和 kayak.de 协同工作,那么这两个域都必须:
在上线之前,请验证您的 well-known 文件是否配置正确且可访问。苹果和谷歌提供了基于 CDN 的测试 URL 来检查文件的可用性:
| 域名 | 苹果 AASA 验证 | 谷歌 Digital Asset Links 验证 |
|---|---|---|
| kayak.com | 测试 AASA 文件 检查苹果 CDN 是否能检索到您的文件 | 测试 assetlinks.json 验证谷歌是否能访问您的 asset links |
| kayak.de | 测试 AASA 文件 检查苹果 CDN 是否能检索到您的文件 | 测试 assetlinks.json 验证谷歌是否能访问您的 asset links |
使用这些测试 URL:
?nocache=1 参数会强制刷新,绕过 CDN 缓存。kayak.com 或 kayak.de 替换为您自己的域名。测试注意事项:确保所有域都正确配置了 well-known 文件。任何一个域上的文件缺失或配置错误都可能导致该域的 Passkey 功能中断。
更多信息: 原生应用中的 WebAuthn Relying Party ID
选择正确的实现方法取决于您应用的认证架构、OAuth 要求以及对会话控制的需求。使用此决策树来确定最佳路径。
从以下关键问题开始:
您的应用是否使用基于 OAuth 的登录(OAuth2、OIDC、社交登录提供商)?
ASWebAuthenticationSession您想在一个类似原生的外壳中复用网页认证(无 URL 栏,完全 UI 控制)吗?
WKWebView + 关联域授权WebView + AndroidX WebKit 1.12.1+ 配置您是在构建新的原生应用还是已有原生登录界面?
您有想要复用的现有网页认证吗?
以下是每种方法在关键维度上的表现:
| 方法 | 创建 Passkey | 使用 Passkey | 管理 Passkey | 技术复杂度 | OAuth 支持 | 设置时间 |
|---|---|---|---|---|---|---|
| 原生实现 | 高采用率 无缝生物识别,最佳 UX | 即时、静默preferImmediatelyAvailableCredentials 可在应用启动时自动显示浮层 | 完全原生控制 与应用设置集成 | 中-高 平台特定 API | 需要独立的 OAuth 流程实现 | 数周到数月 |
| 系统 WebView | 良好采用率 类似浏览器的体验,熟悉 | 标准浏览器 UX 输入框中的 Conditional UI,共享密钥链 | 基于浏览器 用户通过浏览器管理 | 低 极少的原生代码 | 极佳 专为 OAuth 设计 | 数天到数周 |
| 嵌入式 WebView | 较低采用率 需要配置 | 原生 WebAuthn 支持 WebKit 1.12.1+,无 Conditional UI | 有限控制 无原生集成 | 中-高 WebView 配置 + 权限 | 需要配置 | 1-2 周 |
维度解释:
推荐:系统 WebView
如果您的应用通过 OAuth2、OIDC 或社交登录提供商(Google、GitHub、Microsoft 等)进行认证,系统 WebView 是最佳选择:
ASWebAuthenticationSession 专为 OAuth 流程设计。示例:像 kayak.com 和 kayak.de 这样的旅游应用使用 OAuth 进行认证。系统 WebView 允许它们在保留现有 OAuth 基础设施的同时,通过其网页认证页面添加 Passkey 支持。
推荐:混合方法
使用系统 WebView 进行初始 OAuth 认证,然后使用嵌入式 WebView 处理认证后的会话:
何时使用:通过 OAuth 进行认证,但之后需要显示需要直接会话操作的认证后网页内容的应用。
推荐:原生实现
从头开始构建或已有原生屏幕?那就选择完全原生:
preferImmediatelyAvailableCredentials
在应用启动时显示自动 Passkey 浮层——这是原生实现独有的功能,可提供最高的转化率。对于新应用:强烈建议从第一天起就构建原生登录。这为您提供了最佳的 UX,并避免了未来从 WebView 到原生的迁移。
推荐:分阶段迁移
这种分阶段的方法允许增量改进,而不会干扰现有用户。
| 要求 | 原生 | 系统 WebView | 嵌入式 WebView |
|---|---|---|---|
| Well-known 文件 (AASA/assetlinks) | 需要 | 不需要 | 需要 |
| iOS 关联域 | 需要 | 不需要 | 需要 |
| Android WebKit 库 | 不适用 | 不需要 | 需要 (1.12.1+) |
| Relying Party ID | 必须与域名匹配 | 必须与域名匹配 | 必须与域名匹配 |
有关详细的配置说明,请参见第 5 节。
在原生应用中测试 Passkey 需要一个结构化的、多层次的方法。遵循测试金字塔:单元测试(隔离的逻辑)、集成测试(在模拟器/仿真器上进行 WebAuthn 流程)和系统测试(在物理设备上进行端到端测试)。
基本测试类别:
有关全面的测试指南,包括自动化策略、平台特定的陷阱和完整的飞行前检查清单,请参阅我们的专门指南:在原生 iOS 和 Android 应用中测试 Passkey 流程。
考虑在用户成功进行传统登录(密码、OAuth)之后 提示他们创建 Passkey。这种渐进式转换方法:
示例:通过系统 WebView 进行 OAuth 登录后,显示一个原生提示:“想用面容 ID 更快地登录吗?”如果用户接受,则通过在系统 WebView 中加载的网页创建 Passkey。
决定如何实现 Passkey——通过原生实现、系统 WebView 还是嵌入式 WebView——是一个关键的设计选择,它影响着安全性、用户体验和开发复杂度。没有一刀切的答案。
对于基于 OAuth 的应用:系统 WebView(ASWebAuthenticationSession、Chrome Custom Tabs)是推荐的起点。它提供了出色的 OAuth 支持,实现工作量最小,并能自动共享凭据。
对于原生优先的应用:尽早采用原生实现。原生 Passkey 登录能提供最无缝的 UX,并具备
preferImmediatelyAvailableCredentials
等独有功能,这使得应用启动时可以自动显示 Passkey 浮层——这是 WebView 实现无法提供的。随着 iOS 和 Android 现在为 Passkey 提供一流的支持,现实世界的成功案例表明,采用率很高。相关工具(包括开源 SDK 和平台库)已经成熟,使得在合理的时间范围内实现原生集成成为可能。虽然您必须注意设备管理策略、跨设备同步和第三方提供商,但这些挑战可以通过精心的工程设计和测试来管理。其结果是一个能以其简便和速度取悦用户的应用登录,同时显著提高安全性。
对于嵌入式 WebView 框架要求:嵌入式 WebView 通常用于两种现实场景。首先,基于 OAuth 的应用通常使用系统 WebView 进行初始登录流程,然后切换到嵌入式 WebView 在设置屏幕中渲染 Passkey 管理选项,因为那里需要会话控制——尽管一些应用通过在两个流程中都使用系统 WebView 来简化此过程。其次,那些在采用 Passkey 之前就已经在 WebView 框架中嵌入了认证流程的应用,为了保持一致性而继续使用这种模式。带有原生 WebAuthn 支持(AndroidX WebKit 1.12.1+)的嵌入式 WebView 需要配置和设置(权限、授权、WebView 设置),但不再需要自定义的 JavaScript 桥接代码。请注意,嵌入式 WebView 不支持 Conditional UI。当您需要维护现有的嵌入式认证模式或在认证后屏幕需要会话/cookie 控制时,选择此方法。
最终,原生应用中的 Passkey 代表了用户便利性和安全性的巨大飞跃。无论是通过原生、系统 WebView 还是嵌入式 WebView 实现,它们都为您的用户消除了钓鱼风险和密码管理的负担。像 VicRoads 的原生应用 Passkey 集成这样的现实世界实现表明,当正确执行并结合自动 Passkey 浮层等功能时,原生优先的方法能带来最高的用户采用率和满意度。遵循用户友好认证的最佳实践并选择与您应用架构相匹配的实现方法——新应用选择原生优先,OAuth 流程选择系统 WebView,或现有嵌入式模式选择嵌入式 WebView——您就可以提供无密码的生物识别登录,真正实现 Passkey 的愿景:为每个人提供简单、安全和愉快的认证体验。
如果 Passkey 在您的原生应用中不起作用,请按实现方法检查以下常见问题:
application/json.well-known 路径上没有重定向https://your-domain.com (而不是 app://)webcredentials:yourdomain.comASWebAuthenticationSession(推荐)或 SFSafariViewController?mode=developer 进行测试(生产环境移除)WebViewFeature.WEB_AUTHENTICATION 进行运行时功能检查WEB_AUTHENTICATION_SUPPORT_FOR_APP 调用了
setWebAuthenticationSupport()"NotAllowedError: The request is not allowed by the user agent or the platform in the current context"
setWebAuthenticationSupport()
调用没有出现 Passkey 提示
?mode=developer 进行测试、验证 WebView 类型有关详细的调试信息,请参阅我们关于原生应用中 Relying Party ID 的文章。
Corbado 原生 SDK:
平台文档:
验证工具:
Passkeys Series: Native Apps
Related Articles
Passkey Tutorial: How to Implement Passkeys in Web Apps
Vincent - December 7, 2023
The High-Level Architecture of an Integrated Passkey Flow
Janina - December 21, 2022
Table of Contents