进阶 electronjs.org 2026-10-07 23:51:43 · 6 阅读

第8章 代码签名指南

# 第8章 Code Signing 代码签名是一项安全认证技术,用于证明应用确实出自你手。为应用签名后,就不会触发操作系统的安全警告。 Windows 和 macOS 都会阻止用户运行未签名的应用。不签名也能分发应用,但用户必须手动完成多个复杂步骤才能运行。如果你打算打包并分发 Electron 应用,就应该进行代码签名。Electron 生态的配套工具让签名变得很简单——本文档会讲解如何在 Windows 和 macOS 上完成签名。 ## 签名与公证 macOS 构建 准备发布 macOS 应用需要两个步骤:首先对应用进行代码签名,然后将应用上传到 Apple 进行公证,由自动化系统进一步验证你的应用不会危害用户。 开始之前,请确保满足签名和公证的条件: - 注册 Apple Developer Program(需缴纳年费) - 下载并安装 Xcode——这需要一台 macOS 电脑 - 生成、下载并安装签名证书 Electron 生态崇尚配置灵活、自由度高,因此有多种方式可以完成应用的签名和公证。 ### 使用 Electron Forge 如果你使用 Electron 官方推荐的构建工具 Electron Forge,只需在配置中稍作补充,即可完成应用的签名和公证。Forge 是官方 Electron 工具的集合,底层使用 @electron/packager、@electron/osx-sign 和 @electron/notarize。 详细的配置说明请参阅 Electron Forge 文档中的《Signing macOS Apps》指南。 ### 使用 Electron Packager 如果你没有使用 Forge 这类一体化构建流程,那么很可能在用 @electron/packager,它内置了 @electron/osx-sign 和 @electron/notarize。 如果你使用 Packager 的 API,可以在配置中同时传入签名和公证参数。 如果下面的示例不能满足需求,请查阅 @electron/osx-sign 和 @electron/notarize 的文档,了解更多可选配置。 ```js const packager = require('@electron/packager') packager({ dir: '/path/to/my/app', osxSign: {}, osxNotarize: { appleId: 'felix@felix.fun', appleIdPassword: 'my-apple-id-password' ```
}
})
Mac App Store 应用签名 请查阅 Mac App Store 指南。 需要代码签名的 macOS API Electron 暴露的若干 macOS API 依赖于系统框架(例如 Keychain Access 和 Squirrel.Mac)。这些框架仅在应用完成代码签名后才能正常工作。 测试这些 API 时请注意:未签名或仅临时签名(ad-hoc signed)的应用可能出现行为不一致的问题。许多看似 Electron 的 Bug,往往在正确执行签名和公证(notarizing)操作后即可解决: * safeStorage - 若没有有效且一致的代码签名,macOS 可能无法识别未签名应用的不同构建版本属于“同一个应用”。这会导致 Keychain 在每次更新后再次向用户索取权限。 * app.setLoginItemSettings() - 如果应用未打包、未签名或未公证,登录项(Login items)可能会行为异常(例如注册静默失败)。 * cookieEncryption 熔断器(fuse) - Cookie 加密使用了与 safeStorage 相同的操作系统级 Keychain 访问机制,因此具备相同的代码签名要求。 * autoUpdater - Squirrel.Mac 要求应用必须经过签名,自动更新功能才能正常使用。 Windows 构建签名 使用 Azure Artifact Signing Azure Artifact Signing(原名 Azure Trusted Signing)是微软基于云端的现代签名服务。它是 Windows 代码签名的最低成本选项,且能消除 SmartScreen 警告。 目前,Azure Artifact Signing 仅向特定国家的开发者开放。请查阅 Artifact Signing 文档 以确认你的国家是否在该服务支持范围内。 在 Azure Artifact Signing 中使用 jsign 对于 Linux 或 macOS 开发者,可以通过 jsign 借助 Azure Artifact Signing 对 Windows 应用进行签名。使用示例如下: jsign --storetype TRUSTEDSIGNING \
--keystore https://eus.codesigning.azure.net/ \
--storepass $AZURE_ACCESS_TOKEN \
--alias trusted-sign-acct/AppName \
--tsaurl http://timestamp.acs.microsoft.com/ \
--tsmode RFC3161 \
--replace
使用 Electron Forge Electron Forge 是推荐的应用签名工具,同时可用于签名 Squirrel.Windows 安装包和 WiX MSI 安装包。关于 Azure 制品签名的操作指南,请参阅此处。 使用 Electron Builder 关于 Azure 制品签名的 Electron Builder 文档,请参阅此处。 使用传统证书 在对应用进行代码签名之前,你需要获取代码签名证书。与 Apple 不同,微软允许开发者从公开市场购买此类证书。这些证书通常由同时提供 HTTPS 证书的机构出售。价格因供应商而异,因此花时间货比三家可能是值得的。常见的经销商包括: DigiCert EV 代码签名证书 GlobalSign EV 代码签名证书 Sectigo EV 代码签名证书 SSL.com EV 代码签名证书 需要特别指出的是,自 2023 年 6 月起,微软要求软件必须使用“扩展验证”证书进行签名,也称为“EV 代码签名证书”。过去,开发者可以使用一种更简单、更便宜的“Authenticode 代码签名证书”或“基于软件的 OV 证书”来签名软件。这些简易证书目前已不再具有优势:Windows 会将你的应用视为完全未签名,并显示相应的警告对话框。 新的 EV 证书必须存储于符合 FIPS 140 Level 2、Common Criteria EAL 4+ 或同等标准的硬件存储模块中。换句话说,证书无法简单地下载并部署到 CI 基础设施上。实际上,这些存储模块通常外观类似高端 U 盘。 许多证书提供商现在提供“基于云的签名服务”——签名硬件完全托管在其数据中心中,你可以远程使用它来签名代码。由于该方法使得在 CI 环境(如 GitHub Actions、CircleCI 等)中签名应用变得相对容易,因此深受 Electron 维护者的青睐。 截至本文撰写时,Electron 官方应用使用的是 DigiCert KeyLocker,但任何提供文件签名命令行工具的供应商都与 Electron 的配套工具兼容。 Electron 生态系统中的所有工具都使用 @electron/windows-sign,通常通过 windowsSign 属性暴露配置选项。你可以直接使用它来签名文件,也可以在同一份 windowsSign 配置中兼容 Electron Forge、@electron/packager、electron-winstaller 和 electron-wix-msi。 使用 Electron Forge Electron Forge 是推荐的应用签名工具,同时可用于签名 Squirrel.Windows 安装包和 WiX MSI 安装包。关于如何配置应用的详细指南,请参阅 Electron Forge 代码签名教程。 使用 Electron Packager 如果你没有使用如 Forge 这类集成式构建管道,那么你可能正在使用包含 @electron/windows-sign 的 @electron/packager。 如果你使用的是 Packager 的 API,可以传入用于签名应用的配置。 如果以下示例无法满足你的需求,请查看 @electron/windows-sign 以了解众多可能的配置选项。 const packager = require('@electron/packager')

packager({
dir: '/path/to/my/app',
windowsSign: {
signWithParams: '--my=custom --parameters',
// 如果 signtool.exe 不适用于你,可以自定义!
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
}
})
使用 electron-winstaller (Squirrel.Windows) electron-winstaller 是一个可以为你的 Electron 应用生成 Squirrel.Windows 安装程序的包。Electron Forge 的 Squirrel.Windows Maker 底层用的就是它。和 @electron/packager 一样,它底层也使用 @electron/windows-sign,支持相同的 windowsSign 选项。 const electronInstaller = require('electron-winstaller')
// 注意:在 async 函数中使用这种写法,Node 12 还不支持
// 顶层的 await。
try {
await electronInstaller.createWindowsInstaller({
appDirectory: '/tmp/build/my-app-64',
outputDirectory: '/tmp/build/installer64',
authors: 'My App Inc.',
exe: 'myapp.exe',
windowsSign: {
signWithParams: '--my=custom --parameters',
// 如果 signtool.exe 不适用于你,可以自定义!
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
}
})
console.log('It worked!')
} catch (e) {
console.log(`No dice: ${e.message}`)
}
完整的配置选项请查看 electron-winstaller 仓库! 使用 electron-wix-msi (WiX MSI) electron-wix-msi 是一个可以为你的 Electron 应用生成 MSI 安装程序的包。Electron Forge 的 MSI Maker 底层用的就是它。和 @electron/packager 一样,它底层也使用 @electron/windows-sign,支持相同的 windowsSign 选项。 import { MSICreator } from 'electron-wix-msi'

// 第 1 步:实例化 MSICreator
const msiCreator = new MSICreator({
appDirectory: '/path/to/built/app',
description: 'My amazing Kitten simulator',
exe: 'kittens',
name: 'Kittens',
manufacturer: 'Kitten Technologies',
version: '1.1.2',
outputDirectory: '/path/to/output/folder',
windowsSign: {
signWithParams: '--my=custom --parameters',
// 如果 signtool.exe 不适用于你,可以自定义!
signToolPath: 'C:\\Path\\To\\my-custom-tool.exe'
}
})

// 第 2 步:创建 .wxs 模板文件
const supportBinaries = await msiCreator.create()

// 🆕 第 2a 步:如果你的打包脚本中包含对二进制文件的签名,
// 可以选择对辅助二进制文件也进行签名 ```python for (const binary of supportBinaries) {
// 二进制文件包括新的桩可执行文件,以及可选的
// Squirrel 自动更新器。
await signFile(binary)
}

// 步骤 3:将模板编译为 .msi 文件
await msiCreator.compile()
``` 如需查看完整的配置选项,请访问 electron-wix-msi 仓库! 使用 Electron Builder Electron Builder 内置了用于应用程序签名的定制方案,其文档可在此处查看。 Windows Store 应用签名 请参考 Windows Store 指南。

评论 (0)