Electron 桌面应用签名与公证

从准备证书到验证安装包,完成 macOS 和 Windows Electron 应用的基础签名流程。

🎯 引言

打包只是生成应用文件,签名是让操作系统知道“这个应用由谁发布,并且文件没有被发布后修改”。macOS 还需要公证,公证可以理解为把应用交给 Apple 检查后,获得系统认可。

本篇会分别走一遍 macOS 和 Windows 的签名流程。你不需要同时发布两个系统,先选择自己手上的系统练习即可。

先明确三件事:

  • 没有证书时,Forge 不能凭空完成正式签名。
  • 证书和密码不能写进代码仓库。
  • 本地学习可以先不签名,正式分发时再完成签名和平台检查。

🧱 签名流程总览

无论哪个系统,基本流程都类似:

申请并安装证书
    ↓
在 Forge 配置签名信息
    ↓
生成安装包
    ↓
验证签名
    ↓
在干净系统中安装测试

macOS 比 Windows 多一步公证:

macOS 签名 → 上传 Apple 公证 → 下载公证结果 → 验证

🍎 macOS:签名和公证

第一步:在哪里申请 Apple 证书

正式分发到用户电脑时,需要加入 Apple Developer Program,再到 Apple Developer 账号的 Certificates, Identifiers & Profiles → Certificates 页面申请证书。

操作路径是:

  1. 登录 Apple Developer 账号。
  2. 打开 Certificates, Identifiers & Profiles → Certificates
  3. 点击右上角的加号。
  4. 选择 Developer ID Application
  5. 按页面要求创建证书签名请求文件(.certSigningRequest)。
  6. 上传请求文件,下载生成的 .cer 文件。
  7. 双击 .cer,把证书安装到 macOS 的“钥匙串访问”。

Developer ID Application 是给 Mac 应用签名的证书,不要选成只用于 Mac App Store 的证书。Apple 的证书申请页面见:Developer ID certificates

证书安装到当前 Mac 后,先用命令检查:

security find-identity -p codesigning -v

如果列表中能看到 Developer ID Application,说明当前 Mac 已经有可用于应用签名的证书。

Apple Developer 账号、证书申请和 Xcode 页面会更新,本文只说明签名所需的证书类型。申请证书时以 Apple 当前页面为准。

第二步:让 Forge 使用证书

forge.config.jspackagerConfig 中加入 osxSign: {}

forge.config.js
module.exports = {
    packagerConfig: {
        icon: './assets/icon',
        osxSign: {},
    },
};

osxSign: {} 的意思是让 Forge 使用当前 Mac 已安装的签名证书。它不是创建证书,只是告诉 Forge“打包时执行 macOS 签名”。

执行打包:

npm run package

第三步:验证签名

把下面路径换成 out 目录中实际生成的 .app 路径:

codesign --verify --deep --strict --verbose=2 \
    'out/electron-course-darwin-arm64/Electron Course.app'

没有报错,说明代码签名校验通过。签名校验通过不代表已经完成公证,公证还要继续执行。

第四步:在哪里提交 macOS 公证

公证不是在 Electron Forge 页面里完成的,而是把已经签名的应用提交给 Apple 的 Notary Service 检查。Forge 会替你调用 Apple 的服务,但你仍然要准备认证信息。

常见认证方式有两种,初学时选择一种即可:

  • Apple ID + 应用专用密码 + Team ID。
  • App Store Connect API Key。

如果使用 API Key,登录 App Store Connect,进入 Users and Access → Integrations → App Store Connect API → Team Keys,创建并下载 API Key。私钥只允许下载一次,要安全保存。具体入口见 Apple 官方说明

下面使用 Apple ID 和应用专用密码:

forge.config.js
module.exports = {
    packagerConfig: {
        osxSign: {},
        osxNotarize: {
            appleId: process.env.APPLE_ID,
            appleIdPassword: process.env.APPLE_APP_SPECIFIC_PASSWORD,
            teamId: process.env.APPLE_TEAM_ID,
        },
    },
};

在当前终端提供这些环境变量,再执行:

export APPLE_ID='你的 Apple 账号'
export APPLE_APP_SPECIFIC_PASSWORD='应用专用密码'
export APPLE_TEAM_ID='你的 Team ID'
npm run make

其中:

  • APPLE_ID:你的 Apple 账号邮箱。
  • APPLE_APP_SPECIFIC_PASSWORD:Apple 账号生成的应用专用密码,不是登录密码。
  • APPLE_TEAM_ID:Apple Developer 账号中的 Team ID。

Forge 会在打包过程中完成签名并提交公证。公证完成后,可以检查应用是否被系统认可:

spctl --assess --type execute --verbose \
    'out/electron-course-darwin-arm64/Electron Course.app'

macOS 需要记住什么

  • osxSign 负责签名。
  • osxNotarize 负责提交 Apple 公证。
  • 签名证书和公证凭证是两件不同的东西。
  • 签名通过不等于公证通过。

🪟 Windows:签名安装程序

第一步:在哪里申请 Windows 证书

Windows 证书不是从 Electron Forge 申请的,而是向代码签名证书服务商申请。申请时选择 Windows Code Signing Certificate,审核通过后通常会获得 .pfx 证书文件和证书密码。

也可以使用 Microsoft 的云端签名服务,但它有地区、账号和组织资格限制。初学时先记住:你需要先从证书服务商或 Microsoft 签名服务获得一个可用的 Windows 签名身份。

Electron Forge 的 Windows 签名说明见:Signing a Windows app

证书一般以 .pfx 文件提供,同时会有证书密码。

.pfx 文件放在项目之外,或者放在不会提交到 Git 的安全目录中。不要把证书复制到 assets,也不要把密码写进 forge.config.js

第二步:配置 Forge

在 Windows 的 Squirrel maker 中填写证书路径和密码:

forge.config.js
module.exports = {
    makers: [
        {
            name: '@electron-forge/maker-squirrel',
            config: {
                certificateFile: process.env.WINDOWS_CERTIFICATE_FILE,
                certificatePassword: process.env.WINDOWS_CERTIFICATE_PASSWORD,
            },
        },
    ],
};

这里使用环境变量,是为了避免密码出现在代码和 Git 历史中。

第三步:生成签名安装包

Windows PowerShell 中执行:

$env:WINDOWS_CERTIFICATE_FILE = 'C:\certs\electron-course.pfx'
$env:WINDOWS_CERTIFICATE_PASSWORD = '证书密码'
npm run make

Forge 会在生成 Squirrel.Windows 安装程序时使用这份证书。安装程序生成后,再用 Windows 的签名工具验证签名:

signtool verify /pa .\out\make\squirrel.windows\x64\*.exe

实际路径和文件名以 out 目录中的产物为准。

Windows 证书购买、Visual Studio SignTool 和 SmartScreen 的要求会更新。本文只覆盖 Forge 的配置和验证,证书申请以证书服务商及 Microsoft 当前文档为准。

🔐 发布前的安全检查

发布签名前,至少检查下面几项:

[ ] 证书文件没有提交到 Git
[ ] 证书密码没有写进源码
[ ] macOS 已通过 codesign 验证
[ ] macOS 对外发布时已完成公证
[ ] Windows 安装程序已通过 signtool 验证
[ ] 在没有开发工具的干净系统中安装并启动
[ ] 签名后的应用仍然能正常更新和卸载

如果使用 CI/CD,证书和密码应该配置为 CI 的加密 Secret,构建脚本只读取环境变量。


🧾 小节总结

  • 签名需要真实的平台证书,Forge 只负责使用证书完成打包签名。
  • macOS 需要 osxSign,对外发布通常还需要 osxNotarize
  • Windows 使用 .pfx 和密码配置 Squirrel maker。
  • 签名完成后要使用系统工具验证,不能只看 Forge 是否执行成功。
  • 证书和密码必须放在安全环境中,不能提交到 Git。

❓ 知识问答

Q1:没有证书能不能学习 Electron?

A:可以。学习阶段先执行 npm run packagenpm run make,签名可以等到正式分发时再做。

Q2:macOS 签名和公证是一回事吗?

A:不是。签名证明应用来源,公证是 Apple 对应用进行检查并记录结果。

Q3:为什么不能把 .pfx 放进项目?

A:.pfx 通常包含私钥,泄露后别人可能冒用你的发布身份。

Q4:Forge 打包成功,是否代表签名一定成功?

A:不一定。必须使用 codesignsigntool 验证最终产物。

🧪 小练习

练习一:在自己的开发机上执行证书查询命令,确认系统是否存在可用签名证书。

练习二:检查 .gitignore 是否包含本地证书文件、环境变量文件和签名日志。

🎉 现在你已经掌握了 Electron 签名流程中“证书、Forge 配置、构建和验证”的完整关系。