4. iOS Universal Links 实现:Apple App Site Association 文件配置、HTTPS 要求、验证流程与常见失败原因

4.1 原理概述

Universal Links 是 Apple 提供的深层链接机制,允许你的 iOS 应用直接响应用户点击的 HTTPS 链接,无需经过 Safari 中转。当系统检测到该 HTTPS 域名对应的 apple-app-site-association(AASA)文件且内容匹配已安装的应用时,会直接唤起应用并将链接转发给应用处理。如果应用未安装,则回退到域名对应的普通网页。

核心依赖关系如下:

  • 应用必须关联一个支持 HTTPS 的域名(服务器需通过 TLS 1.2+ 提供服务)。
  • 服务端必须托管 JSON 格式的 apple-app-site-association 文件(无 .json 扩展名)。
  • iOS 应用内配置 Associated Domains 权限(applinks: 前缀)。
  • 应用冷启动/后台启动时,系统会自动下载并验证该文件。

配置与验证流程总览

Universal Links 配置与验证流程图 ① AASA 文件 ② HTTPS 服务器 ③ Xcode 关联域名 ④ 应用安装 / 启动 ⑤ 系统下载 AASA ⑥ 验证结果 匹配 / 不匹配 ⑧ 成功:应用接收链接 ⑨ 失败:Safari 打开 注意:AASA 文件必须通过 HTTPS 提供,且响应不可使用重定向。文件必须在应用启动后 60 秒内下载完成才能启用关联。

4.2 Apple App Site Association 文件配置

4.2.1 文件位置与命名

  • 文件名:必须为 apple-app-site-association,不带任何扩展名。
  • 放置目录:/.well-known/apple-app-site-association 或 /apple-app-site-association(根目录)。推荐使用 /.well-known/。
  • MIME 类型:服务器应返回 Content-Type: application/json。

4.2.2 文件内容结构

{
  "applinks": {
    "apps": [],
    "details": [
      {
        "appID": "TEAM_ID.bundle.identifier",
        "paths": [ "/product/*", "NOT /admin/*", "/" ]
      }
    ]
  }
}
  • appID:格式为 TeamID.BundleID。TeamID 在 Apple Developer 账户页面可查,Bundle ID 是 Xcode 中应用的 Bundle Identifier。
  • paths:使用 * 通配符匹配路径,支持 NOT 排除。路径区分大小写。
  • apps:固定为空数组。
⚠️ 常见问题:如果 appID 使用了错误的 TeamID 或 Bundle ID,或 paths 规则写错(例如忘记加 / 前缀),将导致所有 Universal Links 都匹配失败。

4.3 HTTPS 要求

要求项 说明
TLS 版本 支持 TLS 1.2 或更高版本。部分老旧 CDN 配置可能导致验证失败。
证书 必须使用受信任的 CA 签发的证书,自签名证书无效。
重定向 iOS 系统明确不接受任何重定向。服务器必须直接返回 200 响应。
响应大小 小于 512 KB,通常 JSON 文件体积很小,基本不存在超标风险。
Cache-Control 推荐设置 Cache-Control: public, max-age=3600,避免过于频繁的校验。

4.4 验证流程

4.4.1 服务器端验证

使用 curl 检查 AASA 文件是否可访问且内容正确:

curl -v https://yourdomain.com/.well-known/apple-app-site-association

确认响应码为 200,且返回内容是你配置的 JSON。

4.4.2 iOS 侧验证

应用首次联网启动时,系统会自动下载 AASA。你可以通过以下方式检查是否生效:

  1. Safari 地址栏输入链接:按住(或长按)链接,弹出菜单中应显示“在 [你的应用名] 中打开”。
  2. 使用 Apple 官方验证工具:访问 https://search.developer.apple.com/appsearch-validation-tool/,输入域名进行在线验证。
  3. Xcode 调试日志:连接真机,打开 Xcode → Window → Devices and Simulators → 选择设备 → Open Console。过滤关键词 swcd,搜索 apple-app-site-association 相关的日志。
// 典型有效日志(摘要):
[swcd] SWCDownloadTask: 下载 apple-app-site-association 成功
[swcd] SWCManager: 更新 Associated Domain 记录
[swcd] SWCDownloadTask: 验证通过,启用 applinks:yourdomain.com

4.5 常见失败原因

类别 失败原因 解决方案
网络与服务 AASA 文件被重定向(如 HTTP 301/302) 使用 curl -I 检查响应,确保状态码为 200
文件格式 JSON 语法错误(多逗号、少冒号) 通过 JSON 验证工具(如 jsonlint.com)校验
权限配置 Xcode 中 Associated Domains 配置错误 确保格式为 applinks:yourdomain.com,不含 https:// 前缀
证书问题 服务器使用了不完整的证书链 检查中间证书是否被正确安装,使用 openssl s_client -connect 验证
缓存问题 系统缓存了旧的 AASA 文件 修改文件版本号(如增加 ?v=2 查询参数不可行,系统不缓存 query string。建议清除应用或重装)
路径不匹配 用户点击的 URL 路径未被 paths 覆盖 检查 paths 数组,确认 * 通配符使用是否正确
💡 调试建议:使用 Charles Proxy 或 mitmproxy 抓包 iOS 真机流量,监控 app-site-association 的请求与返回。这可以快速确认文件是否被正确获取以及服务器响应是否符合预期。

4.6 稳定性与性能优化

  • 服务器高可用:AASA 文件所在服务器应保持高可用,避免因服务器故障导致系统下载失败,从而影响关联启用。
  • CDN 支持:如果使用 CDN,确保 CDN 不会缓存过旧的版本,且支持原始服务器 200 状态码直传(部分 CDN 默认将 .well-known 重定向)。
  • 文件更新策略:当需要更改路径规则或新增 appID 时,只需更新服务器上的 JSON 文件。修改后的文件会在应用下次启动并联网后自动下载。建议每次更新后,通过 Apple 验证工具确认。
  • 多团队协作:如果多个应用共用同一域名,AASA 文件中的 details 数组应包含所有应用的条目。确保每个条目的 appID 和 paths 无误。