上下文隔离

上下文隔离是什么?

上下文隔离功能将确保您的 预加载脚本 和 Electron的内部逻辑 运行在所加载的 webcontent网页 之外的另一个独立的上下文环境里。 这对安全性很重要,因为它有助于阻止网站访问 Electron 的内部组件 和 您的预加载脚本可访问的高等级权限的API 。

这意味着,实际上,您的预加载脚本访问的 window 对象并不是网站所能访问的对象。 例如,如果您在预加载脚本中设置 window.hello = 'wave ' 并且启用了上下文隔离,当网站尝试访问window.hello对象时将得到未定义(undefined)。

每个应用程序都应该启用上下文隔离,Electron 12版本之后将默认启用它。

我该如何启用?

从 Electron 12 版本之后它将被默认启用。 对于较低版本,在构建 new BrowserWindow时,它是 webPreferences 中的一个选项。

  1. const mainWindow = new BrowserWindow({
  2. webPreferences: {
  3. contextIsolation: true
  4. }
  5. })

迁移

I used to provide APIs from my preload script using window.X = apiObject now what?

一个常见的方法是从您的预加载脚本中暴露API给加载的网站,而 Electron 提供了一个量身定做的模块帮您不费吹灰之力做到这一点。

修改前:上下文隔离功能关闭

  1. window.myAPI = {
  2. doAThing: () => {}
  3. }

修改后:上下文隔离功能启用

  1. const { contextBridge } = require('electron')
  2. contextBridge.exposeInMainWorld('myAPI', {
  3. doAThing: () => {}
  4. })

contextBridge 模块可以安全地暴露 您在独立运行的预加载脚本中提供的API 给 网站运行所在的上下文。 API 还可以像以前一样,从 window.myAPI 网站上访问。

您可以阅读上方链接中的 contextBridge 文档来全面了解它的限制。 例如,您不能在contextBridge上发送自定义类型和symbol。

安全事项

单单开启和使用 contextIsolation 并不直接意味着您所做的一切都是安全的。 例如,此代码是不安全的。

  1. // ❌ Bad code
  2. contextBridge.exposeInMainWorld('myAPI', {
  3. send: ipcRenderer.send
  4. })

它直接暴露了一个没有任何参数过滤的高等级权限 API 。 这将允许任何网站发送任意的 IPC 消息,这您不会是您希望发生的。 相反,暴露进程间通信相关 API 的正确方法是为每一种通信消息提供一种实现方法。

  1. // ✅ Good code
  2. contextBridge.exposeInMainWorld('myAPI', {
  3. loadPreferences: () => ipcRenderer.invoke('load-prefs')
  4. })