昨天终于心一横开了苹果开发者,一大早开了,想着我要一天搞定上架提交!然而,钱是付了,等到晚上九点多,才成功开通。好嘛,那第二天再努力吧,带着兴奋入睡,第二天一早起来开干。

事实是我把这想得太简单,出了舒适区,就真的想踏入泥沼一样寸步难行。搞了大半天才终于把不用上架的版本签好,晚上之前也把 pkg 打出来了。不容易啊!

下面讲讲一些值得注意的点吧。如果你也打算入坑 Tauri 开发,而且打算构建 macOS应用或者 iOS应用,记得收藏,以后会用到的。

证书

你先得搞清楚,CSR、CER、P12 这些概念分别是啥,不然肯定被 N 个证书搞得晕头转向。

在数字证书和公钥基础设施(PKI)领域,这三个缩写分别代表了证书申请、证书本身以及证书存储的不同阶段和格式。 简单来说,它们的关系可以看作是一个从申请到签发再到打包的过程。

CSR

本质:申请表

当你需要一个正式的 SSL/TLS 证书时,你首先要在服务器上生成一对密钥(私钥和公钥)。CSR 就是由你的公钥和一些身份信息(如域名、公司名称、国家等)组成的请求文件。

作用: 你把这个文件发给证书颁发机构(CA,如 Digicert, Let’s Encrypt)。

隐喻: 办护照时填写的“申请表”。表上有你的照片(公钥)和个人资料,但它还不是护照。

包含: 公钥 + 身份信息 + 数字签名。

CER

本质:正式证件

CA 收到你的 CSR 并核实身份后,会用他们的私钥对你的信息进行签名,生成一个证书文件,通常后缀是 .cer 或 .crt.

作用: 安装在服务器上,向客户端证明你的身份并提供公钥。

隐喻: 已经盖了章的正式“护照”。

包含: 你的公钥、CA 的签名、有效期、颁发者信息。它不包含私钥。

P12

本质:全家桶安装包

.p12 是一种二进制格式的容器,它可以把私钥、公钥(CER)以及中间证书链全部打包在一个文件里,并且通常由密码保护。

作用: 方便迁移。比如你想把证书从一台服务器搬到另一台服务器,直接导出一个 P12 文件即可。在 iOS 开发或 Java 服务中非常常见。

隐喻: 你的“保险箱”,里面装着护照(证书)、开启护照配套的钥匙(私钥)以及其他证明文件。

包含: 证书 + 私钥 + (可选) 证书链。

在解决了证书本质上区别之后,你还要搞清楚苹果自己的 N 种证书。Developer ID Application 用于不上架的分发,上架还要用到 Distribution 和 Mac Installer Distribution 两个证书。

机子里证书有两个,一个 Apple Development,一个 Developer ID Application,不小心把证书导错了一次,排查又卡住。

其次 Tauri 一定程度上有点黑盒,加上对苹果应用开发不熟悉,从 Tauri 那不算太完整的文档里逐步实现签名。而且关键是这些信息还散落在 macOS Application Bundle、macOS Code Signing、App Store 三个页面。

为了理清这三个页面的内容,又得把一堆苹果开发流程中的重要概念搞清楚。

概念

Entitlements

它是一组 key-value 对(权利字典),告诉操作系统“这个 App 允许使用哪些特殊能力”。例如:访问 iCloud、HomeKit、推送通知、相机、App Sandbox 等。这些权利会嵌入到 App 的二进制代码签名里。

iOS / macOS 上架时必须正确声明;Xcode 会自动生成 .entitlements 文件,签名时合并进去。

Notarization

Notarization 翻译过来就是做公证。你把已签名的 macOS App 上传给苹果,它会扫描恶意代码、检查签名问题。

扫描通过后,苹果给你的 App 发一个“公证票据”(ticket),你可以把它“钉”(staple)到 App 上。macOS Gatekeeper(门卫)看到有公证票据,就会放心让用户运行,而不会弹出应用损坏的错误。

使用 Developer ID 证书在 App Store 外分发的 macOS App 必须公证。

Provisioning Profile

一个由苹果服务器签名的 .mobileprovision / .provisionprofile 文件,里面包含:

App ID(Bundle ID)

开发者证书

授权的设备列表(开发阶段)

允许使用的 Entitlements 和服务

上架必须,非上架不需要。

双生配置

在搞清楚上面的概念之后就大概能明白了,Tauri 的构建配置必须分两种。

之前的一个卡点是,签名成功了也公证了,结果反而打不开,签名之前还能用 xattr -cr,现在用了都不行。

{

// ……

"macOS": {

"entitlements": "./entitlements.plist",

"signingIdentity": "Developer ID Application: XXX"

}

// ……

}

问了一轮 AI 以为是不知道什么原因导致的 entitlements 没写进去。但是后来又发现即使通过 codesign --force --deep --options runtime 手动把 entitlements 写进去了,依然打不开。

最后才恍然大悟,Tauri 文档上写的分开 tauri.appstore.conf 文件的必要性……

实际上打包非上架包的时候应该把 entitlements 删掉,这样反倒是打出来的包可以正常运行。

App Store 版本

然后发布 App Store 的版本我们外加一个配置文件 tauri.appstore.conf.json:

{

"bundle": {

"macOS": {

"entitlements": "./entitlements.plist",

"signingIdentity": "Apple Distribution: Dexter Chow (9J69XMW5FC)",

"files": {

"embedded.provisionprofile": "./provisioning/MindElixirMac.provisionprofile"

}

}

}

}

构建时运行:

pnpm tauri build --config src-tauri/tauri.appstore.conf.json --target universal-apple-darwin

App Store 版本不需要公正,跑公正只会提示你需要用 Developer ID Application 证书。因此我们需要把环境变量里公正用到的值清空,这样 Tauri 就不会自动公正了。

pnpm tauri build 之后拿到了 .app,接着还要用 pkgbuild 打包成 pkg.

这两步就用到了上面提到的两个证书:

Apple Distribution → 签 App 本身(。app)

Mac Installer Distribution → 签 安装包(。pkg)

最后使用 Transporter 上传 pkg 包(开了虚拟网卡 Transporter 传不了),注意打包兼容 Intel 芯片的 universal 包,如果不想兼容 Intel 芯片,系统要限定在 12.0 以上。

后话

我真的不敢想象没 AI 我看这些文档要看到何年何月。但是做好了,又觉得其实没那么难。所以确实,一件事做到过和没做到过就是完全不一样。没做到过你会怀疑每一个细节有问题,脑子炸炸的,做到了你就知道大致什么是没问题的。后续再处理问题就简单多了。

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。