0Pricing
Electron Desktop App Development · 课时

上下文隔离与预加载脚本

了解并应用上下文隔离,以保护渲染进程免受恶意脚本攻击,并使用预加载脚本安全地公开 API

上下文隔离与预加载脚本 是 CoddyKit 上的免费 Electron Desktop App Development 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 Electron Desktop App Development 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 Electron Desktop App Development 课程共包含 4 节课。

本课时的部分内容尚未翻译,以英文显示。

Renderer Process Risks

In Electron, your application's user interface runs in a renderer process. This process is essentially a Chromium web page, meaning it's susceptible to common web vulnerabilities like Cross-Site Scripting (XSS).

  • Malicious scripts injected into your web content could potentially gain access to powerful Node.js APIs.
  • This direct access could lead to system-level operations being performed without your knowledge or consent.
  • Protecting the renderer is crucial for app security.

What is Context Isolation?

Context Isolation is a fundamental security feature in Electron. When enabled, it ensures that the JavaScript context of your web page is completely separate from Electron's internal APIs and Node.js environment.

  • It's like having two distinct JavaScript worlds within the same renderer process.
  • One world for your web content, and another for Electron/Node.js.
  • This separation prevents your web page's scripts from directly accessing sensitive APIs.

Good news: Context Isolation is enabled by default since Electron 12!

Two JavaScript Worlds

Imagine your renderer process has two invisible layers:

  • The Web Page Context: This is where your index.html, its scripts, and any loaded libraries (like React or Vue) run. It behaves just like a regular browser tab.
  • The Electron/Node.js Context: This is where Electron's internal modules and Node.js APIs (like fs for file system access) live.

Context Isolation ensures these two worlds cannot directly interact with each other's global objects (like window or document), preventing unauthorized access.

Bridging Isolated Contexts

While isolation is great for security, sometimes your web page needs to interact with native desktop features. This is where preload scripts come in.

  • A preload script runs before your web page loads, but within the Electron/Node.js context.
  • It has access to both Node.js APIs and the web page's window object (before isolation takes full effect).
  • However, to securely expose APIs to the isolated web page, we use a special tool called contextBridge.

Loading a Preload Script

To use a preload script, you must specify its path when creating your BrowserWindow in the main process. Remember to keep contextIsolation set to true for security.

Try running this basic setup:

const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true // Crucial for security!
    }
  });

  mainWindow.loadFile('index.html');
}

app.whenReady().then(() => {
  createWindow();

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit();
});

Secure API Exposure

The contextBridge module is your best friend for securely exposing functionality from your preload script to the renderer's isolated web context.

  • It acts as a secure, one-way bridge.
  • You define what functions or data you want to expose.
  • contextBridge ensures that only these defined APIs are available and that data passed between contexts is properly sanitized.

This prevents malicious scripts in the web page from tampering with your exposed APIs or gaining direct access to Node.js.

Crafting Your Preload Script

Inside your preload.js, you'll use contextBridge.exposeInMainWorld(). This method takes two arguments: a key (how the API will be named in the renderer's window object) and an object containing the functions or values you want to expose.

preload.js:

const { contextBridge } = require('electron');

contextBridge.exposeInMainWorld('myAPI', {
  // Expose a simple function
  sendNotification: (message) => {
    // In a real app, you'd use ipcRenderer.send to talk to main process
    console.log(`Preload script sending notification: ${message}`);
    // Example: new Notification('Title', { body: message });
  },
  // Expose a value
  version: process.versions.electron
});

Accessing Exposed APIs

Once your preload script has exposed an API using contextBridge, your web page's JavaScript can safely access it via the window object, under the key you specified.

index.html (or a script loaded by it):

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title>My Electron App</title>
  </head>
  <body>
    <h1>Welcome!</h1>
    <p>Electron Version: <span id="electron-version"></span></p>
    <button id="notify-btn">Send Notification</button>

    <script>
      // Access the exposed API
      window.addEventListener('DOMContentLoaded', () => {
        document.getElementById('electron-version').innerText = window.myAPI.version;

        document.getElementById('notify-btn').addEventListener('click', () => {
          window.myAPI.sendNotification('Hello from the renderer!');
        });
      });
    </script>
  </body>
</html>

Full Example in Action

Here's the complete main.js for our app. To run this example, create three files: main.js (below), preload.js (content from Scene 7), and index.html (content from Scene 8) in the same directory.

When you run main.js, it will load index.html. The index.html then uses the myAPI object exposed by preload.js to display the Electron version and trigger a 'notification' (logged to console in this simple example).

const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow () {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      contextIsolation: true // Keep this true!
    }
  });

  mainWindow.loadFile('index.html');
  // Open DevTools to see console logs from preload and renderer
  mainWindow.webContents.openDevTools();
}

app.whenReady().then(() => {
  createWindow();

  app.on('activate', function () {
    if (BrowserWindow.getAllWindows().length === 0) createWindow();
  });
});

app.on('window-all-closed', function () {
  if (process.platform !== 'darwin') app.quit();
});

Context Check

Time to test your understanding of context isolation and preload scripts!

Secure Foundations

You've learned how to secure your Electron application's renderer process!

  • Context Isolation is key to preventing direct access between untrusted web content and powerful Node.js APIs.
  • Preload scripts run in an isolated environment, allowing you to bridge this gap safely.
  • contextBridge is the secure method within preload scripts to expose carefully selected APIs to your web content.

By using these features, you build a robust and secure foundation for your Electron desktop applications. Great job!

常见问题解答

「上下文隔离与预加载脚本」课时是免费的吗?

是的 — 「上下文隔离与预加载脚本」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 Electron Desktop App Development 课程的其余内容,请升级到 CoddyKit PRO。 Electron Desktop App Development 课程共包含 4 节课。

「上下文隔离与预加载脚本」这节课中我会学到什么?

了解并应用上下文隔离,以保护渲染进程免受恶意脚本攻击,并使用预加载脚本安全地公开 API 你通过在浏览器中直接运行的动手代码来练习 Electron Desktop App Development,全天候 AI 导师会在你学习这节课的过程中回答你的问题。

学习 Electron Desktop App Development 需要有经验吗?

无需任何先前经验。CoddyKit 上的 Electron Desktop App Development 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。

「上下文隔离与预加载脚本」课时需要多长时间?

大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。

我能在这节 Electron Desktop App Development 课中编写并运行代码吗?

能。每节 Electron Desktop App Development 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。

此课程中的所有课时

  1. 安全的 IPC 模式
  2. 上下文隔离与预加载脚本
  3. 渲染进程沙箱
  4. 防范远程内容风险
← 返回 Electron Desktop App Development