进阶 electronjs.org 2026-10-07 23:51:43 · 6 阅读

第9章 上下文隔离

# 上下文隔离(Context Isolation) 它是什么?​ 上下文隔离(Context Isolation)是一项安全特性,它保证 preload 脚本和 Electron 的内部逻辑运行在与 webContents 中加载的网页相互隔离的上下文里。这对安全非常重要,可以防止网页访问 Electron 内部模块,或访问 preload 脚本拥有的那些高权限 API。 也就是说,preload 脚本能访问的 window 对象和网页能访问的 window 对象其实是两个不同的对象。举例来说,如果在 preload 脚本里设置了 window.hello = 'wave',那么在上下文隔离开启的情况下,网页访问 window.hello 时会得到 undefined。 从 Electron 12 开始,上下文隔离默认开启,同时也是所有应用推荐的安全配置。 迁移​ 「之前不开上下文隔离时,我都是在 preload 脚本里用 window.X = apiObject 的方式暴露 API,现在该怎么做?」 之前:上下文隔离关闭时​ 在渲染进程的 preload 脚本中向加载的网页暴露 API 是很常见的需求。在上下文隔离关闭时,preload 脚本和渲染进程共享同一个全局 window 对象,因此可以直接在上面挂载任意属性: preload.js// contextIsolation 关闭时的 preload
window.myAPI = {
doAThing: () => {}
}
然后就可以在渲染进程中直接调用 doAThing() 函数: renderer.js// 在渲染进程中使用暴露出来的 API
window.myAPI.doAThing()
之后:上下文隔离开启时​ Electron 提供了一个专门的模块来帮你无痛完成这件事。通过 contextBridge 模块,可以把 API 从 preload 脚本所在的隔离上下文安全地暴露给网页所在的上下文。网页端依然可以像从前一样通过 window.myAPI 访问这些 API。 preload.js// contextIsolation 开启时的 preload
const { contextBridge } = require('electron')

contextBridge.exposeInMainWorld('myAPI', {
doAThing: () => {}
})
renderer.js// 在渲染进程中使用暴露出来的 API
window.myAPI.doAThing()
请阅读上面的 contextBridge 文档,充分了解它的限制。例如,你不能通过 bridge 传递自定义原型或 Symbol。 安全注意事项​ 仅仅开启 contextIsolation 并使用 contextBridge,并不意味着你所做的一切就自动安全了。比如下面这段代码就是不安全的: preload.js// ❌ 错误代码
contextBridge.exposeInMainWorld('myAPI', {
send: ipcRenderer.send
})
这段代码未经任何参数过滤,直接暴露了功能强大的 API,意味着任何网站都能发送任意的 IPC 消息,这是你极力想要避免的。正确暴露基于 IPC 的 API 的方式,是为每条 IPC 消息提供一个独立的方法。 preload.js// ✅ 良好实践
contextBridge.exposeInMainWorld('myAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
在 TypeScript 中的使用 如果正在用 TypeScript 构建 Electron 应用,需要为通过 context bridge 暴露的 API 添加类型定义。如果不通过声明文件扩展类型,渲染进程的 window 对象就不会具备正确的类型提示。 假设 preload.ts 脚本如下: preload.tscontextBridge.exposeInMainWorld('electronAPI', {
loadPreferences: () => ipcRenderer.invoke('load-prefs')
})
可以创建 interface.d.ts 声明文件,并全局增强 Window 接口: interface.d.tsexport interface IElectronAPI {
loadPreferences: () => Promise
}

declare global {
interface Window {
electronAPI: IElectronAPI
}
}
这样做可确保 TypeScript 编译器在编写渲染进程脚本时,知晓全局 window 对象上的 electronAPI 属性: renderer.tswindow.electronAPI.loadPreferences()

评论 (0)