返回博客

Tauri 白屏不报错,原来是 TLS 主机名不匹配

上周发布了一个 Tauri macOS 桌面应用的新版本。本地 cargo tauri dev 一切正常,打包安装后启动——内容区纯白,标题栏和红绿灯按钮都在,就是没有任何页面内容。没有 Chromium 的「您的连接不是私密连接」警告,没有 console 报错,没有任何线索。

第一反应:是不是 CSP 配置有问题?改了几遍 capabilities/*.json 毫无变化。又怀疑是前端 bundle 没正确打进去,反复 cargo tauri build 还是白屏。折腾了将近一小时,最后才想到去查 TLS。

现象

  • Tauri 应用启动后,app.windows[].url 指向的远程 HTTPS 地址内容区全白
  • 没有 Chromium 风格的证书错误页,没有任何 in-app 错误提示
  • 用浏览器直接打开同一 URL 完全正常
  • curl -k https://<目标域名> 返回正确 HTML;curl(不加 -k)退出码 60

根因

WKWebView(macOS)和 WebView2(Windows)在遭遇 TLS hostname validation 失败时,会把这次导航当作「加载取消」处理,既不渲染错误页,也不触发任何可见的错误状态——WebView 直接停在初始空白文档上。

这和普通浏览器的行为截然不同。Chrome / Firefox 会渲染一张带「继续访问」按钮的中间页,但系统级 WebView 不合成这张页面。

这次的具体原因是服务器 nginx 配置漏了一个 vhost:新上线的子域名没有对应的 server_name 块,请求落到了 nginx 默认 server block,默认 block 挂的是另一个域名的证书,Subject/SAN 完全对不上目标主机名。TLS 握手从连接层看是「成功」的(证书本身有效),但主机名校验失败,WebView 拒绝渲染。

坑:WebView 的 TLS hostname mismatch 不显示错误页

WKWebView / WebView2 遇到证书主机名不匹配时,只是静默白屏,不会像 Chrome 那样弹出「NET::ERR_CERT_COMMON_NAME_INVALID」警告页。在 release 构建里也没有 DevTools 可以打开。很容易把这个服务端问题误判为 CSP、capabilities 或前端 bundle 问题,在客户端反复折腾。

正解

先用 curl 从外部诊断,不要在客户端瞎猜。

# 不加 -k,让 TLS 校验跑起来
curl -v "https://<目标域名>" --max-time 5 2>&1 \
  | grep -E "subject:|SSL:"
 
# 如果看到类似这行,就是这个问题:
# SSL: no alternative certificate subject name matches target host name '<目标域名>'

确认是 hostname mismatch 之后,去服务器上检查 nginx vhost 覆盖情况。最常见的修法是补一个缺失的 server block:

server {
    listen 80;
    server_name <目标域名>;
    return 301 https://$host$request_uri;
}
 
server {
    listen 443 ssl http2;
    server_name <目标域名>;
 
    ssl_certificate     /path/to/fullchain.pem;   # 覆盖该域名的通配符证书
    ssl_certificate_key /path/to/privkey.pem;
 
    location / {
        proxy_pass http://127.0.0.1:<应用端口>;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
    }
}

改完验证:

nginx -t && nginx -s reload
 
# 再跑一次,exit code 应为 0,subject 应匹配目标域名
curl -sv https://<目标域> 2>&1 | grep "subject:"

重新打开桌面应用——不需要重新编译或重新安装,证书在服务端,改完立即生效。

正解:先用 curl 查 TLS,不要在客户端盲猜

白屏排查顺序:先 curl -v https://<目标域名> 看 TLS,再看 nginx vhost 是否覆盖该主机名,最后才考虑客户端 CSP / capabilities 问题。~80% 的 WebView 白屏是服务端问题。

一句话外卖

Tauri / Electron 白屏无报错,先 curl -v(不加 -k)查 TLS,不要在客户端的 capabilities 和 CSP 上浪费时间。