宿主 App 控制不了 WebView 的网络栈。iOS 上,WKWebView 根本无法拦截 HTTPS——Apple 明文规定为 http/https 注册 WKURLSchemeHandler 会抛 NSInvalidArgumentException,而 NSURLProtocol 拦截 http/https 在 WKWebView 中不受支持。Android 的 shouldInterceptRequest 只是「部分」:重定向的后续跳、blob:、javascript: 一概不触发。于是没有宿主强制的证书锁定、没有透明鉴权、没有连接复用、没有请求策略——每个页面重新握手 TLS,数据外泄到未知主机也看不见。宿主自有 runtime 在原生层中介网络:锁定证书、注入签名鉴权、allowlist、统一遥测,页面永远绕不过去。
宿主看不到那根网线
WKWebView 的网络跑在一个独立的网络进程里,Apple 明确禁止覆盖系统自带的 http/https 处理。文档写道:为 WebKit 已经处理的 scheme(例如 https)注册 handler 属于「编程错误」,尝试就会抛 NSInvalidArgumentException。NSURLProtocol 拦截 http/https 在 WKWebView 中不受支持——Apple 自家的开发者关系工程师确认,唯一被认可的路径是自定义 scheme。于是宿主根本无法安插在页面与它的 HTTPS 请求之间。页面要取什么,就走系统自带的 TLS、用系统自带的政策,彻底跳出 App 的掌控。
Android 是「部分」,不是「可控」
Android 上,shouldInterceptRequest(API 21)允许宿主为某个资源返回响应,但它对 javascript:、blob:、android_asset 不触发,重定向时也只有最初那一个资源 URL 会被调用——后续跳转的 URL 一律不回调。即便它确实触发了,也无法在系统自带的 TLS 连接上透明地加请求头,更无法强制证书锁定。这个控制点在 API 文档里看着完整,实践中却漏得厉害:一条重定向链、一段内联 blob、一次脚本发起的 fetch,都会悄悄绕过宿主以为自己已经钩住的东西。
没有可控网络层,你会失去什么
一个宿主无法中介的 WebView,会夺走 App 其余部分视为理所当然的那些控制:
- 证书锁定。 WebView 唯一的钩子是 onReceivedSslError——一个事后才来的「错误」,你可以选择忽略它——这不是真正的锁定。App 原生 HTTP 客户端里随附的防中间人保护,对 WebView 流量并不生效。
- 透明鉴权。 你无法给每一个 WebView 请求附上签名请求头或设备证明,除非用一条页面能侦测或拦截的 JS 桥。
- 连接复用。 每个页面、每个 WebView 都重新握手 TLS;没有宿主级连接池,也没有跨导航的 HTTP/3 0-RTT。
- 请求策略。 你无法在平台层阻止页面向某个未知主机发请求——数据外泄完全不可见。
- 遥测。 你无法像度量原生调用那样,统一度量 WebView 的请求延迟、失败与字节数。
runtime 解法
宿主自有 runtime 在原生层、页面之下中介每一次请求。它按已知集合锁定证书并 fail-closed,把签名鉴权与设备证明注入出站请求、页面永远看不见,维护一个宿主级连接池并协商 HTTP/3,再执行 allowlist——未知主机在 socket 打开之前就被拦下。统一遥测随每个请求一同上报。页面看不到也无法绕过这套策略,因为策略活在页面之下、在 runtime 里,而不在一条它能甩开的桥里。
| 维度 | WebView | 宿主自有 runtime |
|---|---|---|
| HTTPS 拦截 | iOS 不可能;Android 部分 | 原生层拦截,完整 |
| 证书锁定 | 仅有 onReceivedSslError,可绕过 | 强制锁定集合,fail-closed |
| 透明鉴权 | 仅 JS 桥,可侦测 | 签名头 + 设备证明,不可见 |
| 连接复用 | 每页 TLS,无池 | 宿主池 + HTTP/3,0-RTT |
| 请求策略 | 平台层无法拦截 | allowlist,连接前拦截 |
| 遥测 | 无统一视图 | 每请求的延迟/失败/字节 |
本系列反复回到一个事实:WebView 继承了平台最弱的那些面,还额外加了一个「Web 形状」的面。网络是所有面里最基础的一个——而在原生 WebView 里,它恰恰是宿主最无力治理的那一个。runtime 把 App 重新放回网线上,于是流量是 App 该去守护的,而不是系统替它决定的。
参考来源
- Apple 开发者论坛——Quinn「The Eskimo」:WKURLSchemeHandler 只能实现自定义 scheme,无法覆盖 http/https 的内建处理 — 关于 WKWebView 无法拦截标准 HTTPS 的权威陈述。
- WebKit Bug 138169——WKWebView 不支持 NSURLProtocol 式拦截 http/https — 平台长期拒绝提供的那项能力。
- Android 开发者——WebViewClient.shouldInterceptRequest:对 javascript:、blob:、asset 不回调,仅最初重定向 URL — Android 拦截钩子被记载的限制。
- OWASP MASTG——网络通信:WebView 缺少浏览器安全 UI;TLS 策略与锁定必须在 App 层强制 — 为何 WebView 流量需要 App 级控制。
- web.dev——Android 上的 Web:WebView 把渲染内容的完全访问权交给宿主、且缺浏览器安全与隐私控制 — WebView 与加固浏览器之间的结构性缺口。