本章节目标
- 预加载、安全模型的基础概念
- 安全的在渲染进程中,使用被许可的 Node 能力。
预加载(Preload)概念
预加载脚本是在渲染进程加载之前执行的特殊脚本,它运行在一个独立的JavaScript环境中,可以访问Node.js API和Electron的特定API。在创建渲染进程的时候,它会向渲染进程提前注入可访问的api能力。
预加载脚本的主要作用是:
- 在安全隔离的环境中桥接主进程和渲染进程之间的通信
- 向渲染进程暴露受控的API集合
- 在不破坏安全边界的情况下提供必要的功能访问
- 使用
contextBridge.exposeInMainWorld
暴露白名单 API - 通过
ipcRenderer
与主进程通信
安全模型概念
Electron的安全模型基于以下核心原则:
- 上下文隔离(Context Isolation):确保渲染进程无法直接访问Node.js API或Electron的内部API
- 权限最小化:只暴露必要的功能给渲染进程,遵循最小权限原则
- IPC通信机制:通过进程间通信(IPC)实现主进程和渲染进程的安全数据交换
- API白名单机制:使用 contextBridge.exposeInMainWorld 明确定义哪些API可以被渲染进程访问
这种安全模型的设计目的是防止恶意代码在渲染进程中执行危险操作,同时允许开发者安全地提供必要的功能给前端应用。
为什么需要预加载(preload)
Electron框架本身,在进行渲染进程的渲染的时候,有安全相关的基础配置,electron可以允许渲染进程中,直接调用Node的能力,但是这本身是不安全的。
在启用 contextIsolation: true
与 nodeIntegration: false
的前提下,渲染端默认无法直接使用 Node API,需通过预加载桥接受控能力。
简单示例(TypeScript)
以下代码的核心解读如下
1、contextBridge是electron提供的预加载核心能力。
2、contextBridge.exposeInMainWorld函数的第一个参数,会暴露给渲染进程中的window属性上,第二个参数,就是window.api暴露的具体能力。
3、具体访问方式:window.api.getAppVersion()
4、ipcRenderer的作用,是与主进程进行通信,ipcRenderer执行的fs:read-text
必须在主进程中进行定义。
// 预加载脚本代码:preload.js
import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('api', {
getAppVersion: () => ipcRenderer.invoke('app:get-version'),
readTextFile: (filePath: string) => ipcRenderer.invoke('fs:read-text', filePath)
})
以下代码为主进程,定义相关通信能力的代码。
1、ipcMain,主进程进行定义接口能力的api。
2、定义了两个api,分别是app:get-version
和 fs:read-text
主进程处理事件代码:
import { ipcMain, app } from 'electron'
import fs from 'node:fs/promises'
// 处理获取应用版本号请求
ipcMain.handle('app:get-version', () => {
return app.getVersion()
})
// 处理读取文本文件请求
ipcMain.handle('fs:read-text', async (_event, filePath) => {
// 注意:在实际应用中应该添加文件路径验证逻辑
const content = await fs.readFile(filePath, 'utf8')
return content
})
渲染端使用:
// 具体使用
window.api.getAppVersion().then(v => console.log(v))
本章要点
- 明确预加载、安全模型的概念
- 预加载是安全边界,保证可控授权与最小暴露
结语
技术学习是一场持续的旅程,我很荣幸能与你同行。关注这个专栏,让我们共同探索 Electron 的奥秘,在实践中成长,在交流中进步。期待与你一起,从基础概念到项目实战,一步步构建出优秀的桌面应用程序!