这是一个示例,演示如何快速在你的 Electron 项目中启用字节码保护,没有多余的废话。
环境
| tech | version |
|---|---|
| electron | 30.0.6 |
| webpack | 5.91.0 |
| @herberttn/bytenode-webpack-plugin | 2.3.1 |
| nodejs | v20.14.0 |
步骤
Webpack 配置
// 引入依赖
const { BytenodeWebpackPlugin } = require('@herberttn/bytenode-webpack-plugin');
// 在生产环境启用
const isEnvProduction = process.env.NODE_ENV === 'production';
...
plugins: [
isEnvProduction && new BytenodeWebpackPlugin({ compileForElectron: true }),
],
...
// main,preload,renderer 需要更改 entry 配置。我使用了 webpack-merge,如果你没有使用,忽略即可。
// main
const mainConfig = merge(commonConfig, {
// entry: './src/main/main.ts',
entry: {
main: './src/main/main.ts',
},
target: 'electron-main',
output: {
filename: '[name].js',
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
},
...
})
// preload
const preloadConfig = merge(commonConfig, {
// entry: './src/preload/preload.ts',
entry: {
preload: './src/preload/preload.ts',
},
target: 'electron-preload',
output: {
filename: '[name].js',
devtoolModuleFilenameTemplate: '[absolute-resource-path]',
},
});
// renderer
const rendererConfig = merge(commonConfig, {
entry: {
renderer: './src/renderer/renderer.tsx',
},
target: 'electron-renderer',
output: { devtoolModuleFilenameTemplate: '[absolute-resource-path]' },
plugins: [
new HtmlWebpackPlugin({
template: path.resolve(__dirname, './public/index.html'),
}),
],
});
Electron 入口 main.ts/main.js 配置
mainWindow = new BrowserWindow({
...
webPreferences: {
nodeIntegration: true, // 启用 jsc 支持
contextIsolation: false, // false 是启用 jsc 支持,但是用不了 preload 的 contextBridge
preload: path.join(__dirname, './preload.js'), // bytenode 编译后生成的 js,用于加载 preload.compiled.jsc
webSecurity: false,
sandbox: false,
},
});
我知道上面的配置,不符合 Electron 的默认安全配置。但是 Electron 的默认安全配置开启后,你基本上什么也做不了。
如果你希望使用字节码,你必须按照以上配置。
preload contextBridge 修复
contextIsolation: false 会导致 contextBridge 无法使用,这又是 Electron 的一个有趣决定之一。
contextBridge 无法使用,那么你就无法在使用 ipc,当然,你也不需要了。
此时你可以在 renderer 中直接操作 node 的 api,如 fs 等。但是我建议还是通过 preload 中转一下,凡事留一线,日后好相见。
- import { contextBridge } from 'electron';
- import ipcAPI from '_preload/ipc-api';
import loadAddon from "_preload/load_node_addon";
import jb from "_preload/nodejieba";
- contextBridge.exposeInMainWorld('ipcAPI', ipcAPI);
- contextBridge.exposeInMainWorld('myplugin', loadAddon('myplugin'));
- contextBridge.exposeInMainWorld('jb', jb);
+ window.ipcAPI = ipcAPI;
+ window.myplugin = loadAddon('myplugin');
+ window.jb = jb;
完成
通过 webpack.js,main.js,preload.js 中的以上三处配置,你应该可以在你的项目中使用字节码了。
字节码仍然不是最终方案,因为字节码很容易被反编译,目前阶段它只是增加了初级破解者的一些成本。
有些人使用了在 rust 中编写本地插件,和字节码搭配混淆的方案,如果你对代码有强烈的保密需求,可以参考,并在可维护性和安全性上取舍。