因此,我遵循了许多指南来设置Webpack,Electron和React来制作桌面应用程序。完成设置后,我开始工作,并了解到我需要从主机和渲染器获得IPC机制才能进行通信。
import {ipcRenderer} from "electron";
将其添加到我的renderer.js文件会导致错误Uncaught ReferenceError: require is not defined
。
在将我的问题带给一些同事之后,建议我在main.js文件中进行更改
webPreferences: {
nodeIntegration: false,
}
到
webPreferences: {
nodeIntegration: true,
}
我在Google上阅读过的所有内容都非常清楚地表明,如果您关心安全性,那么您应该做的不是 。但是,我能够使用电子ipc的所有资源都使用了ipcRenderer。
现在,互联网上的每个示例是否都存在巨大的安全漏洞,还是我在这里缺少一些关键部分?
我的问题如下。
如果我问错了问题,或者我错过了什么,或者我问这个问题的方式还有其他明显的问题,请让我知道,否则请先谢谢。
答案 0 :(得分:8)
- 是否可以在不启用nodeIntegration的情况下使用ipcRenderer?
可能,但很奇怪。可以使用preload
脚本来完成。
- 如果是,该怎么办?为什么会有这么多资源排除此信息?
可以使用preload
脚本,如下所示。但是,这是not considered secure 。现有的大多数文档都没有显示最佳安全实践。
随后给出一个更安全的示例。
// preload.js
const electron = require('electron');
process.once('loaded', () => {
global.ipcRenderer = electron.ipcRenderer;
});
// main.js
const {app, BrowserWindow} = require('electron');
app.on('ready', () => {
// Create the browser window.
win = new BrowserWindow({
backgroundColor: '#fff', // always set a bg color to enable font antialiasing!
webPreferences: {
preload: path.join(__dirname, './preload.js'),
nodeIntegration: false,
enableRemoteModule: false,
// contextIsolation: true,
// nativeWindowOpen: true,
// sandbox: true,
}
});
win.loadURL(`file://${path.join(__dirname, 'index.html')}`);
注意,预加载脚本的路径必须是绝对路径,这也可以 使用webpack / babel时会变得复杂,因为输出文件可能是不同的路径。
- 如果不是,我该怎么用?
如上所述,尽管可以使用ipcRenderer,但当前的电子安全建议也建议启用contextIsolation
。这将使上述方法无法使用,因为您无法再将数据添加到全局范围。
最安全的建议是AFAIK改为使用addEventListener
和postMessage
,并使用preload脚本作为渲染器和主要脚本之间的桥梁。
// preload.js
const { ipcRenderer } = require('electron');
process.once('loaded', () => {
window.addEventListener('message', event => {
// do something with custom event
const message = event.data;
if (message.myTypeField === 'my-custom-message') {
ipcRenderer.send('custom-message', message);
}
});
});
// main.js
const {app, ipcMain, BrowserWindow} = require('electron');
app.on('ready', () => {
ipcMain.on('custom-message', (event, message) => {
console.log('got an IPC message', e, message);
});
// Create the browser window.
win = new BrowserWindow({
backgroundColor: '#fff', // always set a bg color to enable font antialiasing!
webPreferences: {
preload: path.join(__dirname, './preload.js'),
nodeIntegration: false,
enableRemoteModule: false,
contextIsolation: true,
sandbox: true,
// nativeWindowOpen: true,
}
});
win.loadURL(`file://${path.join(__dirname, 'index.html')}`);
// renderer.js
window.postMessage({
myTypeField: 'my-custom-message',
someData: 123,
});