You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Electron代码签名致macOS应用功能异常,如何实现预期权限行为?

解决Electron macOS签名后权限行为异常的问题

我之前也遇到过类似的Electron应用签名后权限逻辑混乱的情况,结合你的问题细节,咱们一步步拆解原因和解决方案:

核心原因分析

你的问题本质是代码签名身份、权限配置(entitlements)和Apple的Hardened Runtime/公证机制之间的冲突

  1. 未签名时,后端进程的单独签名让系统能识别它的权限需求,首次运行正常提示授权;但用Electron Forge签名整个包时,要么覆盖了后端的签名,要么全局entitlements配置不符合Apple的要求。
  2. 你之前的entitlements包含了很多宽松甚至生产环境不允许的权限(比如com.apple.security.cs.debuggercom.apple.security.cs.disable-executable-page-protection),这些会导致公证失败,同时开启Hardened Runtime后会触发权限限制导致功能失效。
  3. 静默授权的问题是因为签名后系统默认信任开发者ID签名的应用,但你的entitlements没有明确声明所需权限,导致系统跳过提示直接授予,但这种授权可能存在上下文不匹配,后续容易出问题。

分步解决方案

1. 清理并修正Entitlements配置

首先要把entitlements精简到仅必要权限,同时明确声明后端需要的桌面、麦克风等权限。替换你的entitlements.plist为以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <!-- Electron运行必需的权限 -->
  <key>com.apple.security.cs.allow-jit</key>
  <true/>
  <key>com.apple.security.cs.allow-unsigned-executable-memory</key>
  <true/>
  <key>com.apple.security.cs.disable-library-validation</key>
  <true/> <!-- 允许Electron加载第三方库 -->

  <!-- 后端进程需要的权限 -->
  <key>com.apple.security.device.audio-input</key> <!-- 麦克风权限 -->
  <true/>
  <key>com.apple.security.files.user-selected.read-write</key> <!-- 允许访问用户选择的文件(含桌面) -->
  <true/>
  <!-- 如果需要直接访问桌面目录(无需用户选择),可以替换为:
  <key>com.apple.security.files.desktop.read-write</key>
  <true/> -->

  <!-- 如果你需要自动化权限,保留这一项 -->
  <key>com.apple.security.automation.apple-events</key>
  <true/>
</dict>
</plist>

注意:移除了debuggerdisable-executable-page-protection这类生产环境不允许的权限,这些是导致公证失败的核心原因。

2. 修正Electron Forge签名配置

调整package.json中的osxSignosxNotarize配置,重点注意:

  • 使用Developer ID Application身份(不是Mac Developer,后者仅用于开发测试,公证需要生产级的Developer ID)
  • 强制开启Hardened Runtime(Apple现在要求公证必须开启)
  • 配置正确的公证参数(避免脚本返回false)
"osxSign": {
  "entitlements": "entitlements.plist",
  "entitlements-inherit": "entitlements.plist",
  "identity": "Developer ID Application: ME (my id)", // 替换为你的生产开发者ID
  "hardened-runtime": true,
  "gatekeeper-assess": false, // 暂时关闭,等签名稳定后再开启
  "ignore": [
    "./path/to/your/backend-process" // 跳过对后端进程的重新签名,保留你之前单独签的版本
  ]
},
"osxNotarize": {
  "appleId": "your-apple-id@example.com",
  "appleIdPassword": "@keychain:AC_PASSWORD", // 推荐用钥匙串存储密码,避免明文泄露
  "teamId": "your-team-id" // 你的Apple开发者团队ID
}

3. 确保后端进程的签名一致性

  • 后端进程必须用同一个Developer ID签名,这样整个应用包的签名链是统一的,系统会认可它的权限需求。
  • 在Electron Forge的packagerConfig中,把后端进程添加到extraResources,确保它被正确打包到应用包内:
"packagerConfig": {
  "extraResources": [
    "./path/to/your/backend-process" // 替换为你的后端进程路径
  ]
}

验证效果

完成以上配置后,重新执行打包、签名、公证流程:

  1. 首次运行应用时,系统会像未签名时一样弹出权限请求(麦克风、文件访问等)
  2. 授权后后续启动无需重复提示
  3. 公证脚本会返回成功,应用能正常通过Gatekeeper验证

为什么之前的配置会出问题?

  • 公证失败:你之前的entitlements包含了Apple不允许在生产签名中使用的权限,公证服务会直接拒绝。
  • 静默授权:签名后系统信任开发者ID,但你的entitlements没有明确声明权限,系统跳过提示直接授予,但这种授权可能导致后端进程无法正确获取权限上下文。
  • Hardened Runtime开启后功能失效:缺少必要的权限声明,同时存在冲突的宽松权限,导致系统强制限制了后端进程的资源访问。

内容的提问来源于stack exchange,提问作者kakyo

火山引擎 最新活动