返回

VPN导致assetlinks.json无法访问?修复App Links失效指南

Android

VPN 环境下的 Android App Links 难题:assetlinks.json 无法访问?

不少 Android 开发者会碰到这么个头疼事:App Links 配置好了,用 VPN 也能访问到服务器上的 assetlinks.json 文件,可 App Links 就是不生效,点链接还是弹出选择框,或者干脆没反应。这是怎么回事呢?如果你也遇到了 assetlinks.json 文件藏在 VPN 后面导致 App Links 失灵的问题,这篇文章或许能帮到你。

问题浮出水面:App Links 为何在 VPN 后失效?

你可能已经做了这些:

  1. 在 App 的 AndroidManifest.xml 文件里配置好了 <intent-filter>,加上了 android:autoVerify="true"
  2. 按照规范生成了 assetlinks.json 文件,并且把它部署到了你的网站服务器上,放在了 https://your.domain.com/.well-known/assetlinks.json 这个路径。
  3. 为了安全,你的服务器设置了访问限制,只有通过公司的 VPN 才能访问。
  4. 你在连接了 VPN 的测试手机上,用浏览器或者 curl 命令,确实能成功访问到 https://your.domain.com/.well-known/assetlinks.json
  5. 但当你在手机上点击指向 https://your.domain.com/ 的链接时,系统并没有直接用你的 App 打开,而是弹出了应用选择框,或者干脆就用浏览器打开了。App Links 的自动验证(auto-verification)似乎没起作用。

问题就在这儿:明明我的设备能通过 VPN 访问到 assetlinks.json,为什么 App Links 还是不行?

刨根问底:App Links 的验证机制

要弄明白为什么 VPN 会捣乱,得先了解 Android App Links 的域名验证是怎么工作的。

简单说,当你在 AndroidManifest.xml 里给 <intent-filter> 加上 android:autoVerify="true" 时,你是在告诉 Android 系统:“嘿,帮我确认一下,这个 App 真的有权代表 your.domain.com 这个域名处理链接。”

这个确认过程,不是由你的手机直接去访问 https://your.domain.com/.well-known/assetlinks.json 来完成的。出于安全和效率考虑,Android 系统把这个验证任务交给了 Google 的服务器 (可以理解为一个官方的验证服务或者爬虫)。

大致流程是这样的:

  1. 当你的 App 在设备上安装或者更新时,并且声明了 autoVerify="true",Android 系统会通知 Google Play 服务。
  2. Google Play 服务(或者其背后的 Google 服务器)会检查你的 App 声明要关联的域名。
  3. 接着,Google 的服务器会尝试从公共互联网 去访问你指定的 https://your.domain.com/.well-known/assetlinks.json 文件。
  4. 如果 Google 服务器能成功访问到这个文件,并且文件内容有效(比如,包含了正确的应用包名和签名证书指纹),Google 就会记录下这个验证结果。
  5. 设备上的 Google Play 服务会从 Google 服务器同步这个验证状态。如果验证成功,下次用户点击匹配的链接时,系统就会跳过选择框,直接用你的 App 打开。

关键点来了: 执行验证的是 Google 的服务器,这些服务器可没连你的 VPN!它们是从公共互联网进行访问的。所以,就算你的测试手机连着 VPN 能访问 assetlinks.json,Google 的验证服务器却被挡在了外面,访问失败。验证失败,App Links 的自动打开功能自然就失效了。

怎么办?几种应对策略和测试方法

知道了原因,就好对症下药了。既然 Google 的验证服务器需要公网访问权限,而你的 assetlinks.json 又在 VPN 后面,直接让 App Links 像在公网环境下那样“自动验证并直接打开”是行不通的。

不过,这不代表完全没办法测试和处理。下面提供几种思路和方法:

策略一:公网暴露 assetlinks.json(标准做法,但不符合当前场景)

这是最符合 Android App Links 设计初衷的做法,也是官方推荐的方式。

  • 原理:assetlinks.json 文件可以通过公共互联网被 Google 服务器访问到。
  • 操作步骤:
    1. assetlinks.json 文件放置在网站域名的 .well-known 目录下。
    2. 确保 Web 服务器配置正确,允许公网通过 HTTPS 无障碍地访问 https://your.domain.com/.well-known/assetlinks.json,不需要任何登录、认证或 VPN。
    3. 确保服务器支持 HTTPS,并且证书有效。
  • 优点: 完全符合 App Links 规范,验证成功后能实现链接自动打开的最佳用户体验。
  • 缺点: 这直接违背了你最初“assetlinks.json 仅能通过 VPN 访问”的安全要求。如果安全策略允许,这是首选方案。如果不行,请看下面的方法。
  • 安全建议: 如果选择此方案,务必确保证书指纹 (sha256_cert_fingerprints) 是正确的,并且只包含你的发布版应用签名信息。不要包含开发或调试签名的指纹。

策略二:本地测试与手动验证(推荐用于开发测试)

既然自动验证走不通,我们可以在开发和测试阶段“绕开”它,重点关注 App 本身是否能正确处理链接。

  • 原理: 不依赖 Google 的自动验证,而是使用 Android Debug Bridge (adb) 工具在本地设备上强制关联应用和链接,或者手动触发链接,观察 App 的响应。这可以帮你确认 intent-filter 配置是否正确,以及 App 内部处理逻辑是否OK。

  • 操作步骤:

    1. 确保 assetlinks.json 文件格式正确: 就算 Google 访问不到,文件本身的语法、包名、证书指纹也必须是对的。你可以使用 Google 提供的 Statement List Generator and Tester 工具来生成和检查文件内容。

    2. 连接测试设备并确保 VPN 已连接: 这样设备本身可以访问 VPN 内的资源(如果你的 App 在处理链接时还需要访问其他 VPN 内接口的话)。

    3. 使用 adb 检查和模拟链接处理: 打开终端或命令行,执行以下 adb 命令 (将 <package_name> 替换为你的应用包名,your.domain.com/path 替换为你要测试的链接):

      # 查看当前 App Links 状态 (可能显示 PENDING 或 NONE,因为无法自动验证)
      adb shell pm get-app-links <package_name>
      
      # 模拟点击链接,看系统是否能解析到你的 App (可能会弹出选择框)
      adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d "https://your.domain.com/path"
      
    4. (Android 12 及以上) 手动批准链接: 对于 Android 12+ 的设备,你可以在设备的 “应用信息” -> “打开方式” (Open by default) 设置里,手动添加并批准支持的链接。这可以在无法自动验证时,强制让系统用你的 App 打开链接。

    5. (进阶,不常用) 使用 adb 强制关联 (主要用于临时调试): 在某些 Android 版本(尤其较新版本),可以用以下命令(谨慎使用,仅限测试):

      # (注意: 这个命令可能不是所有设备都支持或行为一致, 且只在当前设备生效)
      # 尝试强制设置链接处理偏好 (旧版可能用 set-preferred-activity)
      # adb shell pm set-app-link <package_name> always your.domain.com
      # 验证设置
      # adb shell pm get-app-links --user cur <package_name>
      

      这个命令的效果是临时的,且仅对当前调试设备有效,它模拟了验证成功后的状态,让你测试链接是否直接打开 App。

  • 优点:

    • 无需修改服务器配置,保持 assetlinks.json 的 VPN 保护。
    • 可以有效测试 App 的 intent-filter 配置和对链接的响应逻辑。
  • 缺点:

    • 无法测试 Google 的自动验证流程。
    • 在最终用户设备上,如果 assetlinks.json 仍然不可公网访问,链接仍然不会自动打开 App(用户需要手动选择或批准)。
  • 安全建议: 确保本地测试时使用的 assetlinks.json 包含的是正确的生产签名指纹,这样能更准确地模拟发布后的情况(即使验证本身无法完成)。

策略三:利用内部测试渠道

你可以使用 Google Play Console 的内部测试轨道 (Internal Testing) 或类似机制,分发需要 VPN 才能完整使用的 App 版本给内部测试人员。

  • 原理: 虽然 Google 的自动验证服务器仍然无法穿透 VPN 访问 assetlinks.json,但测试人员可以安装应用,并手动连接 VPN。然后,他们可以点击链接,测试 App 是否出现在选择器中,以及选择 App 后能否正确处理链接逻辑(例如,根据链接参数展示特定内容)。
  • 操作步骤:
    1. 在 Google Play Console 设置内部测试轨道,上传你的 App Bundle 或 APK。
    2. 将需要测试的内部人员(他们应该有权限访问 VPN)添加到测试列表中。
    3. 测试人员通过 Play Store 安装内部测试版的 App。
    4. 测试人员连接 VPN。
    5. 测试人员点击相关的 https://your.domain.com/path 链接。
    6. 观察行为:是否弹出选择框?选择你的 App 后是否正常工作?
  • 优点: 可以在一个相对真实的分发环境中,由具备网络条件的真人进行功能测试。
  • 缺点: 同样,这不能解决 assetlinks.json 验证问题本身,链接通常还是需要用户手动选择 App 才能打开。测试重点在于确认选择 App 后的功能正常。

策略四:条件性暴露 assetlinks.json (复杂且有风险)

这是一个技术上可能,但操作复杂且有维护成本和安全风险的方案。

  • 原理: 配置你的 Web 服务器或防火墙,只允许来自已知的 Google IP 地址范围的请求访问 assetlinks.json 文件,而对其他所有公网 IP(包括普通用户)则阻止访问或要求 VPN。
  • 操作步骤:
    1. 获取 Google 的 IP 列表: Google 公布了一些用于其服务的 IP 地址范围 (例如 Googlebot 的 IP)。你需要找到可能用于 App Links 验证的 IP 段。这是一个难点,因为这些 IP 可能变化,且官方不一定提供专门用于 App Links 验证的固定列表。
    2. 配置访问控制: 在你的 Web 服务器(如 Nginx, Apache)或防火墙上设置规则,允许来自这些 Google IP 的请求访问 .well-known/assetlinks.json,拒绝所有其他外部 IP。同时,保持 VPN 访问策略不变。
    3. 持续监控和更新: Google 的 IP 地址可能变更,你需要定期检查并更新你的访问控制列表。
  • 优点: 理论上可能让 Google 的自动验证成功,同时对普通公网用户隐藏 assetlinks.json
  • 缺点:
    • 高风险! 难以确保获取的 Google IP 列表完整且准确。错误的配置可能导致验证失败,或者意外地将文件暴露给非预期访客。
    • 维护困难。 IP 列表需要持续更新,非常繁琐。
    • 不保证一定有效,因为 Google 的验证机制细节和使用的 IP 可能并不完全公开透明。
  • 安全建议: 非常不推荐 这种方法,除非你对网络安全和服务器配置有非常深入的了解,并能承担维护和潜在风险。错误配置的后果可能很严重。

关键点总结:直面现实

回到最初的问题:Can Android App Links work when assetlinks.json is only accessible via VPN?

答案是:标准意义上的“自动验证并直接打开”的 App Links 功能,在这种情况下无法工作。 因为 Google 的验证服务器需要从公网访问 assetlinks.json,而 VPN 挡住了这条路。

这并不意味着你完全无法处理或测试相关的链接。核心思路是:

  1. 接受现实:assetlinks.json 受 VPN 保护的情况下,你无法获得无缝的、无需用户选择的应用自动打开体验。用户点击链接时,系统会展示应用选择框。
  2. 重心转移: 把测试重点放在确保你的 App 能够正确注册 intent-filter,并且在用户手动选择了你的 App 后,能够正确解析链接、处理参数并导航到合适的页面或执行相应操作。
  3. 利用本地工具: 大量使用 adb 命令进行本地开发调试,验证 App 对链接的响应。
  4. 结合测试流程: 利用内部测试渠道,让有 VPN 权限的测试者验证整个流程(从点击链接到 App 内功能)。
  5. 沟通预期: 如果是面向内部用户的应用,要让用户知道点击链接可能需要手动选择一次 App。

最终,如果“链接自动打开”是一个硬性要求,你可能需要重新评估将 assetlinks.json 文件置于 VPN 保护之后的安全策略是否适用于这个特定文件,或者探索其他不需要公网 assetlinks.json 验证的深度链接方案(例如自定义 URL Scheme,但它们体验不如 App Links)。