在开放 Web 上,点一下通行密钥就唤起系统认证器完成登录。在嵌入式 WebView 里,恰恰是这条流程会崩:WebAuthn 依赖 WebView 无法可靠提供的浏览器与平台能力,且通行密钥绑定的是宿主 App 的域名,不是你的。宿主自有 runtime 桥接设备原生认证器——同一个 API,在每种引擎上都能登录。

Android:WebView 不支持 WebAuthn

权威的集成指南写得很明确:Android 系统 WebView「不支持 WebAuthn」,而 Android 上的 FIDO 依赖 Google Play Services 触达页面。在嵌入式 WebView 内,整个仪式无法保证有平台认证器,于是 navigator.credentials.create() 与 .get() 可能抛错或静默无作为。即便底层引擎本可支持,控制 WebView 的是宿主 App 而非真实浏览器,Safari 或 Chrome 能跑完的整套通行密钥仪式无从保证。Yubico 的兼容性矩阵印证了这一点:在 Android 上,FIDO 能力由 Google Play Services 提供,而非 WebView 组件本身。

iOS:WKWebView 里 navigator.credentials 缺失

在 iOS 上情况更尖锐。开发者报告与通行密钥指南显示,navigator.credentials 只在 SFSafariViewController 与 ASWebAuthenticationSession 中可用,不在大多数 App 嵌入的 WKWebView 里——调用它会报「WebAuthn not implemented on iOS」。更糟的是,WKWebView 内的通行密钥绑定的是宿主 App 的 Associated Domains,而不是你的依赖方域名:用户从 Instagram 或抖音里打开你的站点,无法使用你的通行密钥,因为 WebView 绑定的是它们的域名。条件 UI——在用户名输入框直接浮现凭据的自动填充——在 WebView 内同样不被支持。

通行密钥失效时,什么会崩

  • 无密登录死路。 你最倚仗的快速、抗钓鱼登录,恰恰是在内置浏览器里失败的那条。
  • 安全密钥 MFA 失败。 WebAuthn 第二因子与可发现凭据根本不会启动。
  • 用户回退到密码与 OTP。 最慢、最易放弃的路径成了唯一选择。
  • 失败不可见。 从未启动的仪式不会产生任何服务端调用,于是分析面板看到的是「莫名放弃」而非错误。

runtime 解法

宿主自有 runtime 桥接设备原生认证器。页面调用统一 API——runtime.createPasskey() 与 runtime.authenticateWithPasskey()——宿主驱动 Android 的 FIDO2 / Play Services 与 iOS 的 ASAuthorizationPlatformPublicKeyCredentialProvider(或在认证步骤打开 ASWebAuthenticationSession)。由宿主控制的 Associated Domains 把通行密钥绑定到你的站点。一次集成,每种引擎,一次真实的硬件级登录。

维度WebView宿主自有 runtime
WebAuthn API缺失 / 不一致统一桥
Android 路径WebView 无 WebAuthnFIDO2 / Play Services
iOS 路径WKWebView:navigator.credentials 缺失原生 ASAuthorization
域名绑定宿主 App,非你的站点宿主控制的 Associated Domains
条件 UIWebView 内不支持原生
可观测性客户端静默失败服务端可见

原生 App 能在每台设备上用通行密钥登录,裸 WebView 几乎一台都登不了。runtime 给页面一个认证器——最终产出真实的硬件级登录。

参考来源