Appearance
隔离进程
上下文隔离
上下文隔离是从安全角度考量的,即不允许 webcontent
网页使用electron内部组件与node等权限 。 默认情况下 electron 是开启上下文隔离的。
因为使用Electron开发的桌面应用,是比较特殊的。他是使用网页开发的,所以会引用第三方的应用,如果不进行隔离,这些应用是有机会调用node.js api 的,如果应用是恶意的,就会对用户电脑带来案全隐患。
使用上下文隔离对团队开发好处也是明显的,可以让熟悉vue、react的前端工程师专门编写前端页面逻辑,让熟悉nodejs与electron的开发者负责node.js程序编写。
变量隔离
关闭上下文隔离后,网页脚本可以使用electron与node api等部分高级api。
下面是在 main.js 中禁用上下文隔离的方法
...
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
contextIsolation: false,
nodeIntegration: true,
},
...
禁用上下文隔离后 preload.js与renderer.js没有隔离机制,在preload.js中定义的变量可以在renderer.js中直接使用。
在 preload.js 定义全局变量
window.bm = 'abc'
现在可以在 renderer.js 网页脚本中访问了
console.log(window.bm)
exposeInMainWorld
禁用上下文隔离后 contextIsolation: false,在preload.js中则不需要使用 contextBridge.exposeInMainWorld 向 renderer.js 中提供接口了。
main.js主进程定义IPC事件
const { app, shell } = require('electron')
const { BrowserWindow, ipcMain } = require('electron/main')
const path = require('path')
const createWindow = () => {
const win = new BrowserWindow({
width: 500,
height: 500,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
contextIsolation: false
},
})
win.webContents.openDevTools()
win.loadFile(path.resolve(__dirname, 'index.html'))
}
app.whenReady().then(() => {
createWindow()
//定义IPC事件处理程序
ipcMain.handle('show', () => {
return 'banmashou.com'
})
})
preload.js 直接定义接口
const { ipcRenderer } = require('electron')
const { contextBridge } = require('electron/renderer')
window.api = {
show: () => ipcRenderer.invoke('show'),
}
renderer.js 渲染脚本使用
window.api.show().then((res) => {
console.log(res)
})
nodeIntegration
可以通过修改 main.js 中的 nodeIntegration 配置,来开启node支持,这时就可以在preload.js或renderer.js中使用fs 等高级模块了。
...
const win = new BrowserWindow({
width: 500,
height: 500,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
nodeIntegration: true,
},
})
...
preload.js 默认只能使用有限的 node.js api,不能使用 fs 等高级模块,但开启 nodeIntegration 后,就可以使用了。
const { readFileSync } = require('fs')
const res = readFileSync('package.json', {
encoding: 'utf-8',
})
console.log(res)
如果想在 renderer.js 中使用 node.js 高级模块也是可以的,需要在 main.js 文件中关闭上下文隔离 contextIsolation: false 和开启node支持 nodeIntegration: true
...
const win = new BrowserWindow({
width: 300,
height: 300,
x: 1500,
y: 100,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
contextIsolation: false,
nodeIntegration: true,
},
})
...
进程沙盒
当 Electron 中的渲染进程被沙盒化时,它们的行为与常规 Chrome 渲染器一样。 一个沙盒化的渲染器不会有Node.js 环境。
在沙盒中,渲染进程只能通过进程间通讯 (inter-process communication, IPC) 委派任务给主进程的方式,来执行需权限的任务 (例如:文件系统交互,对系统进行更改或生成子进程) 。
如果我们想在preload.js中使用node.js与electron高级应用,如shell、fs等,可以通过关闭沙盒完成。当然通过开启 nodeIntegration 也可以实现该功能,但这会让renderer.js也可以使用node.js高级api,这是不安全的。
所以,开启沙盒,可以赋予preload.js高级权限,但不影响renderer.js。
- electron默认是开启沙盒模式的
- nodeIntegration:true 时会自动开启沙盒
- sandbox: false 时 preload.js 可以使用nodejs、electron的高级api,如fs模块
基本使用
下面演示在关闭沙盒后,可以在 preload.js 中使用electron的shell模块
main.js主进程中禁用沙盒模式
const { app, shell } = require('electron')
const { BrowserWindow } = require('electron/main')
const path = require('path')
const createWindow = () => {
const win = new BrowserWindow({
width: 500,
height: 500,
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
//关闭沙盒模式
sandbox: false,
},
})
win.webContents.openDevTools()
win.loadFile(path.resolve(__dirname, 'index.html'))
}
app.whenReady().then(() => {
createWindow()
})
关闭沙盒模式后preload.js 中可以使用shell模块打开链接了
const { shell } = require('electron')
shell.openExternal('https://www.banmashou.com')
自动关闭沙盒
以下代码表示禁用上下文隔离,设置了 nodeIntegration:true 也会关闭沙盒。
...
webPreferences: {
preload: path.resolve(__dirname, 'preload.js'),
contextIsolation: false,
nodeIntegration: true,
},
...
这时可以在renderer.js渲染进程脚本中使用 node 与 electron api 等部分高级api。
const { shell } = require('electron')
shell.openExternal('https://www.banmashou.com')