iOS Release 版本开启调试功能

在 iOS 开发中,对外发布的 TestFlight 版或者正式版都是以 Relase 方式构建。而我们一般会在 Debug 模式下开启某些调试功能或打印日志,但是这些操作在 Release 无效。
当我们需要在 Release 版本中启用调试功能时,就不太方便了。而解决这个问题似乎没有很优雅的方式。
在读过 https://andrewking.ca/2020/04/how-to-enable-custom-debugging-in-release-builds/?utm_campaign=iOS%2BDev%2BWeekly&utm_medium=email&utm_source=iOS%2BDev%2BWeekly%2BIssue%2B454 这篇文章后,发现一个比较新奇的方法。
常规方式
文章前半部分提供了几种可能的方式,比如:
使用一个新的配置定义
TESTFLIGHT。
在发版本的时候打两个包,一个是开启 TESTFLIGHT 配置,另一个关闭 TESTFLIGHT。但这并不能很好的区分哪个包对应的是什么配置。
硬编码
userId。
代码中维护 userId 列表,只对指定的 userId 生效。但添加/删除需要修改代码,且有些功能并不需要登录。这种方式可以进一步延伸到使用 deviceId,通过服务端下发列表。
检查安装来源。
区分 TestFlight/App Store/本地 build 几种安装方式。而苹果并没提供官方 API 来获取来源,作者提供了一个 hack 的方式,但可靠性有待确定,因为这种方式极大的依赖苹果实现。
使用秘密的手势。
使用某种复杂的手势来作为开关。但是如果有用户知道了这个手势,也可以调起调试功能。
这种方式让我想起上家公司有关某个功能调试开关的实现,思路比较好玩。
在 app 的某个页面,比如「设置 - 关于我们」(最好是无额外点击事件的页面)。把当前页面按照数字 0-9 分为 10 个虚拟区域,类似拨号键盘排布。如下图所示:

而密码就是当前的手机时间,以 4 位数字表示,不足补 0。在页面上按照预设区域输入当前时间(当前实际上看不到任何分隔线的,估摸大致区域),即可打开调试开关。
使用秘密的
url scheme。
通过特定 url scheme 来唤起 app,以开启调试功能。但它有几个弊端:
为了防止被破解,
url不能太简单,而且开发者需要记住该url,调试不便。由于需要在浏览器中输入
url,那么意味着需要离开app进行操作,增加调试成本。如果有其他人意外知道了
url,同样也可以调试。
重头戏
下面重头戏来了,其方式是通过检测一个特殊的描述文件 Debug Profile 是否在机器上安装,来确定是否开启调试功能。
这种方式有如下好处:
如果想要调试就必须有描述文件,而普通用户无法获取。
只需安装一次描述文件。
一个描述文件 可以被多个
app使用,不同优先级的功能可以使用不同的描述文件。从
App Store安装的app也可以使用,因为只需要有描述文件。不需要特殊的环境和用户。
但是也有其坏处:
需要创建存储证书、 描述文件。
需要根据检查证书信任结果来确定是否安装了描述文件,并且作者承认,检查方式有一点
hack。需要将描述文件存起来,不能丢失。
原理
这种方式是基于 SecTrustEvaluate 方法来验证证书是否受信任。
使用 SecTrustEvaluate 来确定用户是否安装且信任了证书(通过安装描述文件),还是仅仅打包在 app 中未受信任的证书。
因此我们需要做的事情如下:
创建证书
创建和安装描述文件
检查证书是否被信任
下面我们来一步步的操作。
1. 创建证书
打开证书助理,选择创建证书颁发机构。

填入名称和邮箱,反选
Make this CA the default,并勾选Let me override defaults。

点击继续,修改有效期为
7300天,即为20年。

下一步,选择证书。这里我选择的是自己账号的证书。

接下来,一直下一步,直至创建完成。

点击 Show CA Certificate 可以看到成功创建的证书。

2. 创建叶子证书
打开证书助理,选择创建证书颁发机构
填入名称和邮箱,反选
Make this CA the default,并勾选Let me override defaults。
注意这里跟第一步有所不同:
Identity Type选择intermediate CA。User Certificate选择custom,找到第一步中创建的xx.certAuthorityConfig文件。其目录在~/Library/Application Support/Certificate Authority/<your CA name>/<your CA name>.certAuthorityConfig

修改有效期,同第一步中对应的操作
。选择证书,同第一步中对应的操作
。选择发行者。
这里选择第一步中创建的证书,我的证书名是 summer。

一路下一步,直至完成
3. 导出叶子证书
在 Keychain Access 中,选中第 2 步创建的 leaf certificate ,右键导出为 cer 格式,并加入到自己的工程中。
4. 导出 CA 证书
在 Keychain Access 中,选中第 1 步创建的 root certificate ,右键导出为 cer 格式。不需要添加到工程。
5. 创建 Debug 描述文件
下载
Apple Configurator 2点击
File -> New Profile在
General中填入描述文件名称。在
Certificates一栏中选择在第4步中导出的root.cer。cmd+s保存Profile,取个合适的文件名,这里我将其命名为custom-debug.mobileconfig。

6. 编写检测代码
这里我将原文中的 SecTrustEvaluate 替换为了SecTrustEvaluateWithError,因为 SecTrustEvaluate 在 iOS 13 上不再推荐使用。
SecTrustEvaluateWithError 的返回值为 bool。若为 true,则表示信任;若为 false,则表示不受信任。
代码如下:
7. 在需要调试的机器上安装描述文件
将手机用
USB连上电脑,选择对应的设备。点击添加,选择
Profiles,再选择第5步中创建的描述文件。

此时,在手机上会出现描述文件已经下载的提示。如下图所示:

同时 Apple Configurator 是下图状态,等安装完成会自动消失。

安装描述文件。打开
手机设置 -> 通用 -> 描述文件与设备管理,选择对应的描述文件进行安装。
8. 运行工程
运行工程,会发现此时 SecTrustEvaluateWithError 返回的 result 为 YES。

另外可以自行测试一下,如果移除了描述文件 Debug Profile,该结果则为 NO。
版权声明: 本文为 InfoQ 作者【liu_liu】的原创文章。
原文链接:【http://xie.infoq.cn/article/ba40bc882f9f4377c723cf929】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。











评论