上下文隔离
自 Electron 12 以来,默认情况下已启用上下文隔离,并且它是所有应用程序推荐的安全设置。
上下文隔离是什么?
上下文隔离功能将确保您的 预加载脚本 和 Electron的内部逻辑 运行在所加载的 webcontent网页 之外的另一个独立的上下文环境里。 这对安全性很重要,因为它有助于阻止网站访问 Electron 的内部组件 和 您的预加载脚本可访问的高等级权限的API 。
这意味着,实际上,您的预加载脚本访问的 window 对象并不是网站所能访问的对象。 例如,如果您在预加载脚本中设置 window.hello = 'wave' 并且启用了上下文隔离,当网站尝试访问window.hello对象时将返回 undefined。
进程沙盒化
从 Electron 20 开始,渲染进程默认启用了沙盒,无需进一步配置。 如果你想禁用某个进程的沙盒,请参阅为单个进程禁用沙盒部分。
上下文隔离是什么?
Chromium的一个关键安全特性是,进程可以在沙盒中执行。 沙盒通过限制对大多数系统资源的访问来减少恶意代码可能造成的伤害 — 沙盒化的进程只能自由使用CPU周期和内存。 为了执行需要额外权限的操作,沙盒处的进程通过专用通信渠道将任务下放给更大权限的进程。
在Chromium中,沙盒化应用于主进程以外的大多数进程。 其中包括渲染器进程,以及功能性进程,如音频服务、GPU 服务和网络服务。
在 Electron 中沙盒进程 大部分地 表现都与 Chromium 差不多, 但因为介面是 Node.js 的关系 Electron 有一些额外的概念需要考虑。
渲染器进程
当 Electron 中的渲染进程被沙盒化时,它们的行为与常规 Chrome 渲染器一样。 一个沙盒化的渲染器不会有一个 Node.js 环境。
因此,在沙盒中,渲染进程只能透过 进程间通讯 (inter-process communication, IPC) 委派任务给主进程的方式, 来执行需权限的任务 (例如:文件系统交互,对系统进行更改或生成子进程) 。
Preload 脚本
为了让渲染进程能与主进程通信,附属于沙盒化的渲染进程的 preload 脚本中仍可使用一部分以 Polyfill 形式实现的 Node.js API。 有一个与 Node 中类似的 require 函数提供了出来,但只能载入 Electron 和 Node 内置模块的一个子集
require 函数只是一个功能有限的 Ployfill 实现,并不支持把 preload 脚本拆成多个文件然后作为 CommonJS 模块 来加载。 若需要拆分 preload 脚本的代码,可以使用 webpack 或 Parcel 等打包工具。
在渲染器中启用 nodeIntegration 时,沙盒也会被禁用。 可以通过在 BrowserWindow 构造函数中添加 nodeIntegration: true 标志的来实现。
个人实践
- 可以直接在渲染器进程中使用完整的node模块
new BrowserWindow({
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
}
})
- 可以直接在preload环境中使用完整的node模块
new BrowserWindow({
webPreferences: {
nodeIntegration: true,
preload: path.join(__dirname, 'preload.js')
}
})
- 只能在preload环境中使用非常有限的node模块,大部分node、electron模块需要在主进程中调用
new BrowserWindow({
webPreferences: {
preload: path.join(__dirname, 'preload.js')
}
})