上下文隔离
667字约2分钟
2024-12-04
上下文隔离是什么?
上下文隔离是一种机制,旨在将主进程、预加载脚本(Preload 脚本)以及渲染进程分隔开,使它们处于不同的上下文环境中。在这种隔离状态下,主进程与预加载脚本之间的通信只能通过 IPC(进程间通信)来实现。而对于渲染进程和预加载脚本,Electron 提供了专门的 contextBridge 模块,以协助它们之间的通信。
需要注意的是,当启用上下文隔离时,预加载脚本所访问的 window 对象并非网站可访问的对象。例如,若在预加载脚本中设置 window.hello = 'wave',当渲染进程中的网站尝试访问 window.hello 对象时,会返回 undefined。
注意
自 Electron 12 以来,默认情况下已启用上下文隔离,并且它是 _所有应用程序_推荐的安全设置。
预加载脚本注意事项
预加载脚本虽然因为上下文隔离的机制不能访问渲染进程的
window变量,但它可以访问渲染进程的JavaScript DOM API(如 document.getElementById、document.querySelector 等)来操作DOM元素 和 监听页面的事件如DOMContentLoaded。通过预加载脚本传递给渲染进程的
Node对象将会被序列化, 去除了能够访问Node.js和Electron API的方法。如下:
// preload.js
const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', {
getData: () => {
console.log('old ipcRenderer:', ipcRenderer)
return ipcRenderer
}
})console.log('new ipcRenderer:', window.electronAPI.getData())输出结果:

contextBridge 模块
contextBridge 模块是 Electron 提供的一个模块, 它提供了一种安全的方式来将 API 从预加载脚本 Preload 脚本暴露给渲染进程,而不会受到 contextIsolation 的影响。
// 在上下文隔离启用的情况下使用预加载
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})// 在渲染器进程使用导出的 API
window.myAPI.doAThing()安全事项
单开启和使用 contextIsolation 并不直接意味着您所做的一切都是安全的。例如,在使用contextBridge模块暴露API时,应用函数包裹API, 而不要直接暴露API本身。
// preload.js
// ❌ 错误使用
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})它直接暴露了一个没有任何参数过滤的高等级权限 API 。 这将允许任何网站发送任意的 IPC 消息,这不会是你希望发生的。 相反,暴露进程间通信相关 API 的正确方法是为每一种通信消息提供一种实现方法。
// preload.js
// ✅ 正确使用
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})