惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

GbyAI
GbyAI
Cloudbric
Cloudbric
aimingoo的专栏
aimingoo的专栏
D
Docker
量子位
阮一峰的网络日志
阮一峰的网络日志
The GitHub Blog
The GitHub Blog
小众软件
小众软件
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园 - Franky
S
Schneier on Security
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
T
Tor Project blog
Google Online Security Blog
Google Online Security Blog
T
Tenable Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
I
InfoQ
罗磊的独立博客
P
Palo Alto Networks Blog
Security Latest
Security Latest
K
Kaspersky official blog
Apple Machine Learning Research
Apple Machine Learning Research
I
Intezer
C
Cybersecurity and Infrastructure Security Agency CISA
TaoSecurity Blog
TaoSecurity Blog
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
W
WeLiveSecurity
Simon Willison's Weblog
Simon Willison's Weblog
V
V2EX
N
Netflix TechBlog - Medium
爱范儿
爱范儿
S
Secure Thoughts
S
Securelist
MyScale Blog
MyScale Blog
Webroot Blog
Webroot Blog
IT之家
IT之家
Cyberwarzone
Cyberwarzone
Martin Fowler
Martin Fowler
Project Zero
Project Zero
NISL@THU
NISL@THU
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
H
Hacker News: Front Page
H
Heimdal Security Blog
博客园_首页
V
Vulnerabilities – Threatpost
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Recent Announcements
Recent Announcements
Blog — PlanetScale
Blog — PlanetScale
The Cloudflare Blog

一个工匠

AI 发展临界点 - 快上车 流式响应(Chat):HTTP 响应体字节流的读取与解析 iPhone 截屏高效翻译 Flash Open Terminal iPhone 侧载安装 Xcode Symbolic Debug AI 指北 投资风险收益评估 Mac 快速修改系统快捷键 Git Record passkey How to pay apple frameworks Mac - Command Line Tools DNS 的 CNAME 是如何工作的 WebRTC 的一些解释 SSE 指南 1.1.1.1、WARP 和 MASQUE 设备发现 分辨率 - 像素密度 - HiDPI Mac 字体 ESP32 trump - 川普 币圈 - 虚拟货币 【旅游】富士山 【旅游】sakura(樱花) 【旅游】千岛湖 我的 2023 【Swift】中文词语纠错 计算机字符编码与内存编码 - Unicode、UTF8、String 从汇编角度理解 “函数调用栈” 和 “有栈协程” 在 Xcode 中更好的使用 Swift 通过 Swift Package 制作二进制库 Arc 浏览器 - 意外的惊喜 【Swift 三方源码 1】SwiftShell 高效的命令行工具 Swift 脚本开发环境搭建 rime - 小鹤双拼 【旅游】沿海旅游 (威海、青岛) 好记性远远不如烂笔头 高级语言小记 又一年高考 Vision 未来已来 致敬耗子哥 Socket 与 ICMP 对互联网隐私的一些想法 网络代理是如何工作的 (致敬 Surge) 又十年 - 至三十而立 双拼 - 少有的高回报效率技能 Vim 技巧 我的 2022 三年疫情五味杂陈 - 下 老梗 - 浏览器按回车后发生了什么 三年疫情五味杂陈 生活推荐清单 Shell 和进程 有计划的努力 内卷 不确定性 数学可以保障逻辑自洽 这些年我的软件清单 决定做一些改变 函数调用栈之彻底理解 锁 - 共享数据安全指↑ 江苏女有感 碎碎念 - 2022 碎碎念 - 2021 打算记录一些碎碎念 多重性格就是逆天改命 从 Core Foundation 看更大世界 TCP 数据传输过程分析 iOS main 文件中的 @autoreleasepool 的真实用途 多线程的难点在哪里 Objective-C 和 Runtime 早起打卡计划 ing 打比方 IM 和 Socket 的关系及 Heart 的必要性 如果我的人生突然只剩下 8 小时... 胡说八道之雪粉 Array 和 LinkedList 的深刻认知 Swift struct (值类型) 与 class (引用类型) 区别及三种传参机制深刻关系和使用 逃离信用卡和花呗 Swift_let_var_struct_class 网聚人的力量 - 网易 绿皮火车 喝酒十之八九会误事 HKong 胡说八道之云服务 互联网网络传输协议理解坑点 CPU 的制作 我心里一直有一个念想 网络基础协议 为什么 32 位操作系统只能用 4G 内存空间 努力和天赋 洗牙 RAC-Api-Summer iOS 内存原理 Block 闭包简查记录 《白夜行》 谈谈事件驱动 老博新开 祭首
移动端换端方案与场景还原
海驴 · 2024-10-27 · via 一个工匠

换端能力

在移动应用生态中, 换端 (App Switching) 是一个常见的需求。同一台设备上,有以下三个端: M(Web网页)A(移动应用 app)B(待唤端的应用 app)。 当 M 或 A 需要跳转至 B 时, 有两种技术方案: URL Scheme 和 Universal Link。

URL Scheme

  1. App 端先行验证能力:
    • A 可以通过canOpen方法预先判断 B 是否已安装, 且此操作不会触发跳转
  1. Web 端无先行验证能力:
    • M (Web) 无法预先判断 B 是否安装
    • 通常采用延迟判断方案: 执行跳转后等待 2 秒, 根据页面状态判断跳转是否成功

URL Scheme 存在一个严重的安全问题: 不同的应用可以注册相同的 scheme。这意味着当 A 尝试跳转 B 时, 可能会被恶意应用 X/Y/Z 截获。正是由于这个安全隐患, URL Scheme 正逐渐被 Universal Link 替代。

  1. 预判限制:
    • M 和 A 都无法预先判断 B 是否安装
  2. 跳转控制:
    • A 可以通过跳转参数强制使用 Universal Link 进行跳转
    • 跳转执行后可以判断目标应用是否安装

原理 & 挑战

  • 应用安装时, 操作系统会向配置的 domain 请求资源文件 (开发人员提前配置),该文件包含应用约定的 Router 信息
  • 如果 HTTPS 请求失败, 应用将暂时无法被 Universal Link 唤醒
  • Apple 未明确指定重试机制, 仅表示系统会在适当时机重新请求

微信的二次回跳验证机制

二次回跳说明

当应用 A 首次使用微信 SDK 的 Universal Link 功能进行分享时, 会出现双重跳转:

1
A -> 微信 -> A -> 微信

这种情况仅在首次分享时出现, 后续分享操作将直接完成。

双重验证有效性

Universal Link 在安全的前提下,成功率较高,能保证其他 App 跳转到我的 App 的成功率。只要我的 App 配置了 Universal Link,大概率其他 App 跳转到我的 App 是没有问题的。
但是,我的 App 也需要跳转回其他 App,此时我的 App 并不信任其他 App(或者说不信任其他 App 的 Universal Link 配置)。
举个分享流程的例子,如果 A 通过 Universal Link 跳转到微信后,微信处理完分享流程。用户点击返回 A,但无法返回,此时就会造成严重的用户体验缺失(Bug)。

二次回跳处理

微信采用类似 TCP 三次握手的验证机制,提前打通 A 和微信之间的换端通路。这可能涉及到降级处理,即 Universal Link 降级为 URL Scheme。仍以分享流程为例:

  1. A(通过微信 SDK API)使用 Universal Link 跳转到微信。
    • SDK API 增加了选项控制,指定使用 Universal Link 方式。如果失败,直接降级到 URL Scheme 进行跳转,此时不会有二次回跳验证。
  2. 微信拉取服务端资源,将 A 的 URL Scheme 和 Universal Link 拉取到本地(A 提前在微信的开发者平台进行了配置)。
  3. 微信通过 Universal Link 跳转回 A。
    • 指定使用 Universal Link。如果失败,说明 A 的 Universal Link 配置有问题,降级到 URL Scheme 通知 A。后续 A 和微信的操作(分享操作仍需继续)都通过 URL Scheme 完成。
  4. A(通过微信 SDK API)判断微信通过 Universal Link 成功唤起了自己,表明 A 和微信之间的 Universal Link 通路畅通。
    • 后续所有的换端操作,全部通过 Universal Link 完成。
  5. A(通过微信 SDK API)发起真正的分享换端,微信被唤醒后执行分享流程(朋友、朋友圈、收藏等),然后回跳到 A。
  6. 之后,所有换端操作都直接通过 Universal Link 进行,不再需要之前的二次回跳验证。

Web 向原生 App 发起登录验证

web 页面在需要登陆的场景,可能需要跳转到 app 中完成登陆,然后回到到网页中。

处理流程

  1. 唤起阶段:

    • Web 页面 (url_a) 通过 Universal Link 或 URL Scheme 唤起 App
    • 携带必要的身份标识参数
  2. 登录处理:

    • 方案一: 服务端传递 Token

      • App 将 token 和身份标识发送至服务端
      • App 通过 openURL(url_a) 在 Safari 中刷新网页(不会新开页面)
      • Web 根据本地存储的标识参数,从服务器获取 Token。
    • 方案二: 换端传递 Token

      • App 将 Token 拼接到 url_b_{path} 中,通过 openURL 唤醒。
      • Safari 会新开页面,新的页面是登录成功后的落地页。

Delay Deep Link(场景还原 - 一般用于广告投放)

通过 Universal Link,如果目标 App 未安装,此时可以跳转到 Web 中间页并转跳到 App Store。希望用户下载 App 并首次打开后,立即跳转到当初 Universal Link 的承接页。这也叫【场景还原】。
核心原理是,全新的 App 在第一次被打开后,需要通过某种途径,找到之前 Universal Link 中标记的落地页信息。

  1. 方案一:本地

    • 在使用 Universal Link 进行换端时,发起换端的一方负责将换端链接存储到用户的剪贴板中。
    • 当目标 App 打开后,自行读取剪贴板并进行落地页跳转。剪贴板有预探功能,可以先不触发用户的权限弹框,提前知道是否有需要的口令内容。
  2. 方案二:设备标识(Device ID)

    • 这里的 Device ID 并不是真正的设备 ID,而是大家共同遵守的一套规则,可近乎唯一地标记一台设备,并保证漂移率很低。可以根据设备的开机时间、升级时间、系统版本等信息,组合成密钥字符。
    • 在使用 Universal Link 进行换端时,发起换端的一方负责将 Device ID 和落地页信息存储到云端。
    • 当目标 App 打开后,自行获取 Device ID,然后从云端回拉落地页信息。

一般来说,这些场景都牵涉到资金投放,需要尽可能高的识别精度。所以方案都是混合使用,有一个匹配上就算【场景还原】成功了。