看起来Electron的安全性是这样进化的(来源)。
Electron 1 nodeIntegration默认为true
Renderer可以完全访问Node API—如果Renderer加载远程代码,则存在巨大的安全风险。
Electron 5 nodeIntegration默认为false
当设置为false时,将使用预加载脚本向Renderer公开特定的API。(不管nodeIntegration的值如何,预加载脚本总是可以访问Node api)
//preload.js
window.api = {
deleteFile: f => require('fs').unlink(f)
}
Electron 5 contextIsolation默认为true(实际上在Electron 11中仍然默认为false)
这将导致预加载脚本在单独的上下文中运行。你不能再做窗户了。API = ....你现在要做的是:
//preload.js
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('api', {
deleteFile: f => require('fs').unlink(f)
})
电子6 require()节点内置沙盒渲染器不再隐式加载远程版本
如果Renderer有沙盒设置为true,你必须做:
//preload.js
const { contextBridge, remote } = require('electron')
contextBridge.exposeInMainWorld('api', {
deleteFile: f => remote.require('fs').unlink(f)
})
Electron 10 enableRemoteModule默认为false(远程模块在Electron 12中已弃用)
remote模块用于当你需要从沙盒渲染器中访问Node api时(如上面的例子);或者当你需要访问仅对主进程可用的电子api时(如对话框,菜单)。如果没有remote,您需要编写如下所示的显式IPC处理程序。
//preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('api', {
displayMessage: text => ipcRenderer.invoke("displayMessage", text)
})
//main.js
const { ipcMain, dialog } = require('electron')
ipcMain.handle("displayMessage", text => dialog.showMessageBox(text))
Electron 10弃用节点集成标志(在Electron 12中删除)
建议
总是设置{nodeIntegration: false, contextIsolation: true, enableRemoteModule: false}。
为了最大的安全性,设置{sandbox: true}。您的预加载脚本将必须使用IPC调用主进程来完成所有工作。
如果sandbox为false,你的预加载脚本可以直接访问Node API,如require('fs'). readfile。你是安全的,只要你不这样做
//bad
contextBridge.exposeInMainWorld('api', {
readFile: require('fs').readFile
})