- 开发工具
- 桌面应用
- 前端构建
【免费下载链接】forge
:electron: A complete tool for building and publishing Electron applications
本指南基于 Electron Forge 仓库中的 docs/guides/code-signing/code-signing-macos.md 编写,源码佐证来自 packages/api/core/src/api/package.ts 与 packages/maker/pkg/src/MakerPKG.ts。
在 macOS 上,应用分发涉及两层安全技术:代码签名(Code Signing)与公证(Notarization)。代码签名用于证明应用出自你之手、分发前未被篡改;公证则是在代码签名的基础上,将应用提交至 Apple 服务器进行自动化恶意软件扫描的额外验证步骤。本指南面向使用 Electron Forge 打包并分发 macOS 应用的开发者,介绍如何安装证书、在packagerConfig中配置osxSign与osxNotarize,以及如何在forge.config.js中安全地读取凭证。读完本指南,你将能够在 Forge 的 Package 步骤中一次性完成签名与公证配置,并理解其底层调用链与可选参数。
macOS 分发安全体系概览
macOS 应用分发时面临两层安全技术:
- 代码签名:对应用作者身份进行认证,并确保分发前未被篡改。
- 公证:将应用提交至 Apple 服务器进行自动化恶意软件扫描,是额外的一道验证。
从 macOS 10.15(Catalina)开始,应用若要正常运行在用户机器上且不触发额外的系统安全检查,需要同时完成代码签名和公证。唯一的例外是 Mac App Store(MAS)应用:其提交流程本身包含类似的自动化检查,因此不需要公证。因此在packagerConfig中,MAS 与直接分发(Developer ID)场景的签名配置需求是有所区分的。
前置条件
安装 Xcode
Xcode 是 Apple 面向 macOS、iOS 等平台的集成开发环境。虽然 Electron 与 IDE 本身耦合不深,但 Xcode 对以下两个环节必不可少:
- 帮助你安装代码签名证书;
- 公证(notarization)所必需。
在 macOS 上完成签名与公证,Xcode(及其附带的命令行工具)是官方推荐的入口。
获取签名证书
macOS 应用的代码签名证书只能通过购买Apple Developer Program会员资格获得。签名 Electron 应用时,可能需要两个不同的证书:
| 证书 | 用途 |
|---|---|
| Developer ID Installer | 分发给Mac App Store的应用 |
| Developer ID Application | 在Mac App Store 之外直接分发的应用 |
获得会员资格后,需要先将证书安装到本机。官方推荐通过 Xcode 加载证书。安装完成后,可以用以下 shell 命令在终端验证可用的代码签名证书:
security find-identity -p codesigning -v如果输出中列出了你的证书(形如Developer ID Application: Your Name (TEAM1234567)),说明证书已正确安装。
配置 Forge:签名与公证发生在哪个环节
在 Electron Forge 中,macOS 应用的签名与公证发生在Package 步骤,由@electron/packager驱动。packagerConfig中的两个独立选项分别对应这两件事:
osxSign:控制代码签名;osxNotarize:控制公证。
从源码看,这一流程发生在 packages/api/core/src/api/package.ts 中。Forge 会将forgeConfig.packagerConfig展开合并进传给@electron/packager的选项对象(第 417-435 行附近):
const packageOpts: PackagerOptions = { asar: false, overwrite: true, ignore: [/^\/out\//g], quiet: true, ...forgeConfig.packagerConfig, // ... };也就是说,packagerConfig中与@electron/packager兼容的字段(包括osxSign、osxNotarize)都会被透传给底层打包库。而packagerConfig的默认值在 packages/api/core/src/util/forge-config.ts 中定义为空对象{}(第 198 行),这正解释了"osxSign对象必须存在(即使为空)"的原因:配置合并时,只有显式声明的字段才会被带上。
此外,.pkg安装包的制作也复用了同一套osxNotarize配置:在 packages/maker/pkg/src/MakerPKG.ts 中,当config.identity存在且forgeConfig.packagerConfig.osxNotarize存在时,会对生成的.pkg文件调用notarize(第 48-53 行):
if (this.config.identity && forgeConfig.packagerConfig.osxNotarize) { await notarize({ ...forgeConfig.packagerConfig.osxNotarize, appPath: outPath, }); }该行为的测试用例位于 packages/maker/pkg/spec/MakerPKG.spec.ts,分别覆盖"配置了 identity 与 osxNotarize 时执行 notarize"、"缺少 identity 时不 notarize"、"缺少 osxNotarize 时不 notarize"三种场景。
osxSign 选项
Forge 底层使用@electron/osx-sign工具对 macOS 应用进行签名。要启用代码签名,只需保证packagerConfig.osxSign存在:
module.exports = { packagerConfig: { osxSign: {} // 对象必须存在,即使为空 } };osxSign配置自带一组开箱即用的默认值,绝大多数场景下建议从一个空配置对象开始。完整的选项列表可查阅 Forge API 文档中的OsxSignOptions类型;更详细的选项说明可参考@electron/osx-sign的文档。
自定义 entitlements
修改默认osxSign配置最常见的诉求是自定义entitlements。在 macOS 中,entitlements 是授予应用的权限(例如访问摄像头、麦克风或 USB 设备),它们存储于应用可执行文件的代码签名中。
默认情况下,@electron/osx-sign自带一组适用于 MAS 或直接分发目标的 entitlements 文件。如果需要按文件粒度定制,可以使用optionsForFile回调:它接收打包后应用中的每个文件路径,并返回该文件对应的签名选项:
module.exports = { // ... packagerConfig: { // ... osxSign: { optionsForFile: (filePath) => { // 这里保持简单:对每个文件都返回同一个 entitlements.plist。 // 你也可以利用这个回调,把不同的 entitlements 集合 // 映射到打包应用中的不同文件。 return { entitlements: 'path/to/entitlements.plist' }; } } } // ... };如需进一步了解 entitlements 机制,可参考 Apple 开发者文档中的Entitlements与Hardened Runtime页面。
osxNotarize 选项
Forge 底层使用@electron/notarize工具完成公证。notarytool命令支持三种认证方式,下面逐一说明。注意:为了把环境变量加载进 Forge 配置,你需要使用forge.config.js这类 JS 配置文件(而不是纯 JSON 的package.json内联配置)。
务必保护你的认证信息绝不要把认证信息以明文形式写死在配置里。下面的示例都把凭证存放在环境变量中,通过 Node.js 的
process.env对象读取。
方式一:使用 App-Specific Password(应用专用密码)
先从 Apple 生成一个应用专用密码来向notarytool提供凭证。注意:如果更改了 Apple ID 密码,此密码需要重新生成。
使用该策略时,osxNotarize有以下三个字段(其中前两个为必填):
| 字段 | 类型 | 描述 |
|---|---|---|
appleId | string | 与你的 Apple Developer 账号关联的 Apple ID |
appleIdPassword | string | 应用专用密码(不是Apple ID 登录密码!) |
teamId | string | 你要在其名下公证的 Apple Team ID。可以在https://developer.apple.com/account/#/membership找到你所属团队的 Team ID |
module.exports = { // ... packagerConfig: { // ... osxNotarize: { appleId: process.env.APPLE_ID, appleIdPassword: process.env.APPLE_PASSWORD, teamId: process.env.APPLE_TEAM_ID } } // ... };提醒:尽管字段名叫appleIdPassword,它并不是你的 Apple ID 账号密码。
方式二:使用 App Store Connect API Key
在 App Store Connect 的"Team Keys"标签页生成 API Key 来认证notarytool。生成的 API Key 形如AuthKey_ABCD123456.p8,且只能下载一次。
使用该策略时,osxNotarize有以下三个必填字段:
| 字段 | 类型 | 描述 |
|---|---|---|
appleApiKey | string | API Key 文件的文件系统路径 |
appleApiKeyId | string | 10 位字母数字 ID。以AuthKey_ABCD123456.p8为例,该值为ABCD123456 |
appleApiIssuer | string | 标识 API Key 签发者的 UUID,可在生成 API Key 的"Keys"标签页找到 |
module.exports = { // ... packagerConfig: { // ... osxNotarize: { appleApiKey: process.env.APPLE_API_KEY, appleApiKeyId: process.env.APPLE_API_KEY_ID, appleApiIssuer: process.env.APPLE_API_ISSUER } } // ... };方式三:使用 Keychain(钥匙串)
除了通过环境变量把凭证传给 Forge 配置,你也可以使用 macOS 的钥匙串(keychain)保存上述任一方式的凭证。在终端直接执行notarytool store-credentials即可;使用说明可查阅notarytool的 man page:
man notarytool使用该策略时,osxNotarize有以下字段:
| 字段 | 类型 | 描述 |
|---|---|---|
keychainProfile | string | 存放公证凭证的钥匙串配置文件名称 |
keychain(可选) | string | 存放该凭证配置的钥匙串名称(或路径) |
注意:如果你使用notarytool store-credentials保存凭证,keychain参数可以被自动检测到。
module.exports = { // ... packagerConfig: { // ... osxNotarize: { keychainProfile: 'my-keychain-profile' } } // ... };完整示例配置
下面是一份同时配置osxSign与osxNotarize的最小 Forge 配置:
module.exports = { packagerConfig: { osxSign: {}, osxNotarize: { appleId: process.env.APPLE_ID, appleIdPassword: process.env.APPLE_PASSWORD, teamId: process.env.APPLE_TEAM_ID } } };配套参考
- 本指南对应的平台索引页:docs/guides/code-signing/index.md
- Windows 平台的签名指南:docs/guides/code-signing/code-signing-windows.mdx
- 若你使用
.pkg制作器,签名相关的额外配置(如identity、identityValidation)可参考 packages/maker/pkg/src/Config.ts 及其文档 docs/config/makers/pkg.mdx
- 开发工具
- 桌面应用
- 前端构建
【免费下载链接】forge
:electron: A complete tool for building and publishing Electron applications
相关推荐
Tauri macOS 签名与公证:tauri-macos-sign 的证书管理、代码签名与 Notarization 全流程解析
Tauri macOS 签名与公证:tauri macos sign 的证书管理、代码签名与 Notarization 全流程解析 本文以 Tauri 仓库中的
桌面应用跨平台移动开发electron-builder macOS 公证(Notarization)完整指南:签名、Hardened Runtime 与 Stapling 实战
electron builder macOS 公证(Notarization)完整指南:签名、Hardened Runtime 与 Stapling 实战 导读
构建工具桌面应用开发工具Electron代码签名:Windows、macOS应用签名指南
Electron代码签名:Windows、macOS应用签名指南 为什么代码签名如此重要? 在当今的数字时代,用户安全是首要考虑因素。当你分发Electron应
桌面应用跨平台前端
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考