我用
创建了我的 Electron 应用程序create-electron-app $projDir --template=vite-typescript
在我的浏览器窗口的网络偏好设置中
contextIsolation: true
nodeIntegration: false
我已经定义了我想在 preload.ts 内的渲染器上下文中使用的 API,如下所示:
const WORLD_ID: number = 1004;
const API_KEY: string = "api";
interface IApi {
myFun: <T>(...args: any) => Promise<T>;
}
const api: IApi = {
myFun: <T>(...args: any) => ipcRenderer.invoke("my-event", ...args) as Promise<T>
}
contextBridge.exposeInIsolatedWorld(
WORLD_ID, API_KEY, api
);
export { type IApi, API_KEY, WORLD_ID };
我为API定义了一个interface.d.ts:
import { type IApi, API_KEY } from '@/preload';
declare global {
interface Window {
[API_KEY]: IApi
}
}
文档(https://www.electronjs.org/docs/latest/api/context-bridge)建议我现在可以像这样使用api:
// Renderer (In isolated world id1004)
window.api.myFun()
webFrame.executeInIsolatedWorld()
不起作用,因为 webFrame 需要路径模块,而该模块在渲染器中不可用。有替代方案吗?据我了解,在您想要在 Electron 应用程序的渲染器进程中运行未知/不受信任的脚本的情况下,隔离世界可用于提高安全性。想象一下某种插件/扩展系统,应用程序的最终用户可以在其中安装和运行其他用户编写的脚本。您不希望这些扩展脚本相互干扰或与您自己的可信渲染器脚本干扰。
默认情况下,在隔离世界中执行的脚本可以访问 DOM API 和 JavaScript 内置函数。您可以使用 Electron 的
contextBridge.exposeInIsolatedWorld
让隔离脚本访问其他 API。
例如,以下预加载脚本公开了两个 API:
extensionAPI
在主世界可用。它提供了一个功能 extension.execute
,允许应用程序的 Web 前端在隔离世界中执行脚本 1000
。processAPI
在孤立的世界1000
中可用。它允许扩展脚本访问 Node.js process
API 的子集,特别是引擎和库版本。// preload.ts
import { contextBridge, webFrame } from "electron";
const extensionAPI = {
execute: async (source: string): Promise<void> => {
await webFrame.executeJavaScriptInIsolatedWorld(1000, [{ code: source }]);
},
};
contextBridge.exposeInMainWorld("extension", extensionAPI);
const processAPI = {
versions: process.versions
};
contextBridge.exposeInIsolatedWorld(1000, "process", process);
现在,您在主世界中运行的前端代码可以调用
extension.execute
来运行在隔离世界中执行某些脚本。例如:
extension.execute("console.log('Hello, Electron', process.versions.electron)");
这个示例有点做作,并且可能通过在同一个隔离世界中运行所有扩展脚本来违反一些安全最佳实践。我希望它能说明孤立世界 API 的用法。