Electron 源碼保護

Electron 源碼保護

這是一個示例,演示如何快速在你的 Electron 項目中啓用字節碼保護,沒有多餘的廢話。

環境

techversion
electron30.0.6
webpack5.91.0
@herberttn/bytenode-webpack-plugin2.3.1
nodejsv20.14.0

步驟

Webpack 配置

參考文檔

 1// 引入依賴
 2const { BytenodeWebpackPlugin } = require('@herberttn/bytenode-webpack-plugin');
 3// 在生產環境啓用
 4const isEnvProduction = process.env.NODE_ENV === 'production';
 5...
 6plugins: [
 7  isEnvProduction && new BytenodeWebpackPlugin({ compileForElectron: true }),
 8],
 9...
10// main,preload,renderer 需要更改 entry 配置。我使用了 webpack-merge,如果你沒有使用,忽略即可。
11// main
12const mainConfig = merge(commonConfig, {
13  // entry: './src/main/main.ts',
14  entry: {
15    main: './src/main/main.ts',
16  },
17  target: 'electron-main',
18  output: {
19    filename: '[name].js',
20    devtoolModuleFilenameTemplate: '[absolute-resource-path]',
21  },
22  ...
23})
24// preload
25const preloadConfig = merge(commonConfig, {
26    // entry: './src/preload/preload.ts',
27    entry: {
28      preload: './src/preload/preload.ts',
29    },
30    target: 'electron-preload',
31    output: {
32      filename: '[name].js',
33      devtoolModuleFilenameTemplate: '[absolute-resource-path]',
34    },
35});
36// renderer
37const rendererConfig = merge(commonConfig, {
38  entry: {
39    renderer: './src/renderer/renderer.tsx',
40  },
41  target: 'electron-renderer',
42  output: { devtoolModuleFilenameTemplate: '[absolute-resource-path]' },
43  plugins: [
44    new HtmlWebpackPlugin({
45      template: path.resolve(__dirname, './public/index.html'),
46    }),
47  ],
48});

Electron 入口 main.ts/main.js 配置

 1  mainWindow = new BrowserWindow({
 2  ...
 3  webPreferences: {
 4    nodeIntegration: true, // 啓用 jsc 支持
 5    contextIsolation: false, // false 是啓用 jsc 支持,但是用不了 preload 的 contextBridge
 6    preload: path.join(__dirname, './preload.js'), // bytenode 編譯後生成的 js,用於加載 preload.compiled.jsc
 7    webSecurity: false,
 8    sandbox: false,
 9  },
10});

我知道上面的配置,不符合 Electron 的默認安全配置。但是 Electron 的默認安全配置開啓後,你基本上什麼也做不了。

如果你希望使用字節碼,你必須按照以上配置。

preload contextBridge 修復

contextIsolation: false 會導致 contextBridge 無法使用,這又是 Electron 的一個有趣決定之一。

contextBridge 無法使用,那麼你就無法在使用 ipc,當然,你也不需要了。

此時你可以在 renderer 中直接操作 node 的 api,如 fs 等。但是我建議還是通過 preload 中轉一下,凡事留一線,日後好相見。

 1- import { contextBridge } from 'electron';
 2- import ipcAPI from '_preload/ipc-api';
 3import loadAddon from "_preload/load_node_addon";
 4import jb from "_preload/nodejieba";
 5
 6- contextBridge.exposeInMainWorld('ipcAPI', ipcAPI);
 7- contextBridge.exposeInMainWorld('myplugin', loadAddon('myplugin'));
 8- contextBridge.exposeInMainWorld('jb', jb);
 9
10+ window.ipcAPI = ipcAPI;
11+ window.myplugin = loadAddon('myplugin');
12+ window.jb = jb;

完成

通過 webpack.js,main.js,preload.js 中的以上三處配置,你應該可以在你的項目中使用字節碼了。

字節碼仍然不是最終方案,因爲字節碼很容易被反編譯,目前階段它只是增加了初級破解者的一些成本。

有些人使用了在 rust 中編寫本地插件,和字節碼搭配混淆的方案,如果你對代碼有強烈的保密需求,可以參考,並在可維護性和安全性上取捨。