Electron 应用如何在macOS系统进行签名和公证

748 阅读2分钟

签名

1.准备好应用程序签名用的p12证书,证书类型为Developer ID Application

image.png

2.在环境变量中配置p12证书路径和访问密码

open ~/.zshrc,写入如下配置

export CSC_LINK=/Users/newline/Documents/Apple/developerID_application.p12
export CSC_KEY_PASSWORD=123456

CSC_LINK 设置p12证书路径,CSC_KEY_PASSWORD 设置p12证书访问密码, 保存之后,执行source ~/.zshrc,刷新环境变量

3.使用electron-builder 签名打包, package.json 配置内容如下:

{
  "name": "xxxxxx",
  "productName": "xxxx",
  "version": "3.0.3",
  "relaseDate": "20231011",
  "description": "Create By xxxxx",
  "main": "entry/macMain.js",
  "scripts": {
    "start": "electron .",
    "dev": "electron . --debug",
    "pack": "electron-builder --dir",
    "dist": "electron-builder",
    "dist:mac": "electron-builder --mac",
    "postinstall": "electron-builder install-app-deps",
    "prepack": "node script/custom-build-script.js",
    "dist2": "npm run prepack && electron-builder"
  },
  "keywords": [],
  "author": "xxxxxxxx",
  "license": "xxxxxxxxx",
  "build": {
    "afterSign": "sign/notarize.js",
    "appId": "newline.engage",
    "asar": true,
    "asarUnpack": [
      "node_modules/ffmpeg-static/bin/${os}/${arch}/ffmpeg",
      "node_modules/ffmpeg-static/index.js",
      "node_modules/ffmpeg-static/package.json",
      "node_modules/regedit/vbs/*",
      "extraResources"
    ],
    "dmg": {
      "contents": [
        {
          "x": 410,
          "y": 150,
          "type": "link",
          "path": "/Applications"
        },
        {
          "x": 130,
          "y": 150,
          "type": "file"
        }
      ]
    },
    "publish": [
      {
        "provider": "generic",
        "url": "xxxxxxx"
      }
    ],
    "extraFiles": [
      {
        "from": "extraResources",
        "to": "extraResources",
        "filter": [
          "**/*",
          "!hitevk"
        ]
      }
    ],
    "mac": {
      "icon": "src/assets/app-icon/mac/xxxx.icns",
      "artifactName": "${productName}_${version}.${ext}",
      "target": [
        {
          "target": "dmg",
          "arch": "universal"
        },
        {
          "target": "zip",
          "arch": "universal"
        }
      ],
      "fileAssociations": [
        {
          "ext": [
            ".iwb"
          ],
          "name": "xxxxx",
          "description": "xxxx IWB File",
          "role": "Editor"
        }
      ],
      "gatekeeperAssess": false,
      "hardenedRuntime": true,
      "entitlements": "sign/entitlements.mac.plist",
      "extendInfo": {
        "NSCameraUsageDescription": "The current application needs to access your camera, allow it?",
        "NSMicrophoneUsageDescription": "The current application needs to access your camera microphone, allow it?"
      }
    }
  },
  "dependencies": {
    "@electron/remote": "^2.0.8",
    "@spotxyz/macos-audio-devices": "^1.5.0",
    "adm-zip": "file:buildScript/adm-zip",
    "aperture": "^6.1.3",
    "axios": "^1.1.3",
    "electron-log": "^4.4.8",
    "electron-squirrel-startup": "^1.0.0",
    "electron-store": "^8.1.0",
    "electron-updater": "^5.0.1",
    "electron-updater-fqcx": "file:buildScript/electron-updater",
    "fabric": "^5.3.0",
    "fast-xml-parser": "^4.0.11",
    "ffmpeg-static": "file:buildScript/ffmpeg-static",
    "fluent-ffmpeg": "^2.1.2",
    "fs-extra": "^11.1.1",
    "iconv-lite": "^0.6.3",
    "jschardet": "^3.0.0",
    "node-disk-info": "^1.3.0",
    "node-gyp-build": "^4.6.0",
    "node-machine-id": "^1.1.12",
    "pako": "^2.1.0",
    "pdf-lib": "^1.17.1",
    "pdfjs-dist": "3.2.146",
    "progress-stream": "^2.0.0",
    "request": "^2.88.2",
    "usb-detection": "^4.14.1",
    "vue": "2.7",
    "xml2js": "^0.4.23",
    "xmlbuilder": "^15.1.1"
  },
  "devDependencies": {
    "@electron/notarize": "^2.1.0",
    "electron": "19.0.10",
    "electron-builder": "^23.6.0",
    "electron-rebuild": "^3.2.9"
  },
  "__npminstall_done": false
}




entitlements.mac.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>
        <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.allow-dyld-environment-variables</key>
        <true/>
        <key>com.apple.security.device.audio-input</key>
        <true/>
        <key>com.apple.security.device.camera</key>
        <true/>
        <key>com.apple.security.device.microphone</key>
        <true/>
    </dict>
</plist>

公证(notarize)

使用 @electron/notarize 对 Electron 程序进行公证, 安装@electron/notarize

npm

npm install @electron/notarize --save-dev

yarn

yarn add @electron/notarize --dev

在项目中创建公证js文件notarize.js, notarize.js 文件的内容如下:

const {notarize} = require('@electron/notarize')

exports.default = async function notarizing (context) {
  const appName = context.packager.appInfo.productFilename
  const {electronPlatformName, appOutDir} = context
  if (electronPlatformName !== 'darwin') {
    return
  }
  // 获取xxx.app 路径
  let appPath = `${appOutDir}/${appName}.app`
  // 您的苹果开发者帐户的用户名
  let appleId = "xxxx@gmail.com"

// 应用程序专用密码,每次打包之前需要重新生成,公证完成密码即失效
  let appleIdPassword = "wryw-zbbp-yjte-wfhc" 
  // 您要公证的团队ID
  let teamId = "xxxxx"
  console.log("appPath ",appPath)

  // Package your app here, and code sign with hardened runtime
  // 指定公证工具为notarytool
  return  await notarize({ tool: 'notarytool',
    appPath,
    appleId,
    appleIdPassword,
    teamId
  });
}

指定公证工具为notarytool

image.png Apple 已弃用 altool 进行公证,并宣布将于 2023 年 11 月 1 日停止进行公证工作。然而,altool 仍然是执行其他任务的好方法,例如向 App Store 提交应用程序。要将您的工作流程迁移到 notarytool。

appleIdPassword 应用程序专用密码(不是您的 Apple ID 密码,每次打包之前需要重新生成,公证完成密码即失效

image.png

teamId选项。要获取此 ID,请转到您的Apple 开发者帐户,然后单击“会员详细信息”,您将在其中找到您的团队 ID。此链接应该可以直接让您到达那里:https ://developer.apple.com/account#MembershipDetailsCard

项目的 package.json 中最顶层build添加以下配置:


"build": { "afterSign": "sign/notarize.js" }

afterSign: xxx.app 签名之后执行

最终执行npm run dist ,执行签名,公证流程,生成dmg,zip包

image.png