electron 中的那些事(很关键)-核心要点补充

文章目录

    • [electron 开发中核心要点补充](#electron 开发中核心要点补充)
    • 环境变量之鉴权
      • [一、Electron 环境变量的安全配置原则](#一、Electron 环境变量的安全配置原则)
        • [1. 基础安全配置(禁用渲染进程的危险能力)](#1. 基础安全配置(禁用渲染进程的危险能力))
        • [2. 非敏感环境变量的安全传递](#2. 非敏感环境变量的安全传递)
      • [二、敏感信息(如 Token)的安全传递方案](#二、敏感信息(如 Token)的安全传递方案)
        • [方案 1:主进程代理所有 API 请求(最优)](#方案 1:主进程代理所有 API 请求(最优))
        • [方案 2:Token 存储在安全位置,按需通过 IPC 临时获取(次优)](#方案 2:Token 存储在安全位置,按需通过 IPC 临时获取(次优))
        • [方案 3:使用 session 隔离(兜底)](#方案 3:使用 session 隔离(兜底))
      • 三、额外安全加固措施
      • 总结
    • [在非 HTTPS(纯 HTTP)环境下,如何安全处理 Electron 中的 session 和敏感 Token 传递](#在非 HTTPS(纯 HTTP)环境下,如何安全处理 Electron 中的 session 和敏感 Token 传递)
      • [一、HTTP 环境下的核心安全风险](#一、HTTP 环境下的核心安全风险)
      • [二、HTTP 环境下 Session/Token 的安全处理方案](#二、HTTP 环境下 Session/Token 的安全处理方案)
        • [1. 核心方案:主进程代理 API 请求(适配 HTTP)](#1. 核心方案:主进程代理 API 请求(适配 HTTP))
        • [2. 禁用 HTTP 环境下的 Session Cookie 方案(关键!)](#2. 禁用 HTTP 环境下的 Session Cookie 方案(关键!))
        • [3. 兜底方案:HTTP 请求加密(应用层加固)](#3. 兜底方案:HTTP 请求加密(应用层加固))
        • [4. Electron Session 的安全配置(HTTP 环境)](#4. Electron Session 的安全配置(HTTP 环境))
      • [三、HTTP 环境下的额外安全建议](#三、HTTP 环境下的额外安全建议)
      • 总结
    • [electron 版本 与 node 版本之间的关系](#electron 版本 与 node 版本之间的关系)
      • [一、核心关系:Electron 内置 Node.js](#一、核心关系:Electron 内置 Node.js)
        • [1. 版本绑定的原因](#1. 版本绑定的原因)
        • [2. 如何查询对应关系](#2. 如何查询对应关系)
          • [方式 1:官方版本对照表(推荐)](#方式 1:官方版本对照表(推荐))
          • [方式 2:命令行查看当前 Electron 的 Node 版本](#方式 2:命令行查看当前 Electron 的 Node 版本)
          • [方式 3:运行时获取版本信息](#方式 3:运行时获取版本信息)
      • 二、开发中的关键注意事项
        • [1. 原生模块编译依赖 Node 版本](#1. 原生模块编译依赖 Node 版本)
        • [2. 版本升级的兼容性风险](#2. 版本升级的兼容性风险)
        • [3. 长期支持(LTS)版本选择](#3. 长期支持(LTS)版本选择)
      • 三、版本选择建议
      • 总结

electron 开发中核心要点补充

electron 向渲染进程提供哪些环境变量才能保证应用安全,敏感的如token 怎么传递才能满足渲染进程框架鉴权的需求

session存储的安全性在https可以设置,如果不是https 是http 怎么办,session 如何处理
electron 版本 与 node 版本之间的关系

环境变量之鉴权

一、Electron 环境变量的安全配置原则

首先要明确:绝对不要直接将敏感环境变量暴露给渲染进程 。Electron 中渲染进程默认可以通过 process.env 访问 Node.js 环境变量,这会带来极大安全风险。

1. 基础安全配置(禁用渲染进程的危险能力)

先通过主进程配置限制渲染进程的权限,从根源降低风险:

javascript 复制代码
// main.js (主进程)
const { app, BrowserWindow } = require('electron');
const path = require('path');

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // 核心安全配置
      nodeIntegration: false, // 禁用渲染进程的 Node.js 集成(关键!)
      contextIsolation: true, // 开启上下文隔离(关键!)
      sandbox: true, // 可选:开启沙箱,进一步限制权限
      preload: path.join(__dirname, 'preload.js'), // 预加载脚本(唯一安全通道)
      // 禁用远程模块(Electron 14+ 已移除,低版本需手动禁用)
      enableRemoteModule: false,
      // 限制脚本执行(可选,根据业务需求)
      allowRunningInsecureContent: false,
      webSecurity: true // 启用网页安全策略
    }
  });

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

app.whenReady().then(createWindow);
2. 非敏感环境变量的安全传递

非敏感的环境变量(如应用版本、API 基础地址)可通过预加载脚本的 contextBridge 暴露,而非直接暴露 process.env

javascript 复制代码
// preload.js (预加载脚本,必须是独立文件)
const { contextBridge } = require('electron');
// 仅暴露非敏感环境变量
const safeEnv = {
  API_BASE_URL: process.env.API_BASE_URL || 'https://api.example.com',
  APP_VERSION: process.env.APP_VERSION || '1.0.0'
};

// 向渲染进程暴露安全的环境变量(命名空间需唯一,避免冲突)
contextBridge.exposeInMainWorld('electronSafeEnv', safeEnv);

渲染进程中使用:

javascript 复制代码
// renderer.js (渲染进程)
console.log(window.electronSafeEnv.API_BASE_URL); // 仅能访问暴露的非敏感变量

二、敏感信息(如 Token)的安全传递方案

Token 属于核心敏感数据,绝对不能通过环境变量、全局变量或预加载脚本直接暴露,推荐以下 3 种安全方案(优先级从高到低):

方案 1:主进程代理所有 API 请求(最优)

核心思路:渲染进程仅传递"请求参数",不接触 Token;主进程持有 Token 并代理所有 API 调用,渲染进程仅接收最终结果。

javascript 复制代码
// 1. 主进程 (main.js) - 持有 Token 并监听 IPC 请求
const { ipcMain } = require('electron');
let authToken = ''; // 仅在主进程存储 Token

// 初始化 Token(如从安全存储读取)
function initToken() {
  authToken = 'your-secure-token-from-storage'; // 从加密文件/系统密钥库读取
}

// 监听渲染进程的 API 请求
ipcMain.handle('api:request', async (event, options) => {
  try {
    // 主进程携带 Token 发起请求
    const response = await fetch(options.url, {
      method: options.method || 'GET',
      headers: {
        'Authorization': `Bearer ${authToken}`, // Token 仅在主进程使用
        'Content-Type': 'application/json',
        ...options.headers
      },
      body: options.body ? JSON.stringify(options.body) : null
    });
    const data = await response.json();
    return { success: true, data };
  } catch (error) {
    return { success: false, error: error.message };
  }
});

// 2. 预加载脚本 (preload.js) - 暴露安全的 API 调用方法
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
  // 暴露 API 请求方法,渲染进程仅传递参数,不接触 Token
  requestAPI: (options) => ipcRenderer.invoke('api:request', options)
});

// 3. 渲染进程 (renderer.js) - 调用 API,无感知 Token
async function fetchUserInfo() {
  const result = await window.electronAPI.requestAPI({
    url: '/api/user/info',
    method: 'GET'
  });
  if (result.success) {
    console.log('用户信息:', result.data);
  } else {
    console.error('请求失败:', result.error);
  }
}
方案 2:Token 存储在安全位置,按需通过 IPC 临时获取(次优)

若必须让渲染进程短暂持有 Token(如适配现有前端鉴权框架),可将 Token 存储在主进程的安全存储(如 keytar 或 Electron 的安全存储 API),渲染进程通过鉴权后临时获取:

javascript 复制代码
// 1. 主进程 - 安全存储/获取 Token
const keytar = require('keytar'); // 需安装:npm install keytar
const SERVICE_NAME = 'YourAppName';
const ACCOUNT_NAME = 'user-auth';

// 存储 Token 到系统密钥库(macOS Keychain/Windows Credential Manager)
ipcMain.handle('token:save', async (_, token) => {
  await keytar.setPassword(SERVICE_NAME, ACCOUNT_NAME, token);
  return true;
});

// 鉴权通过后临时获取 Token(需验证请求合法性)
ipcMain.handle('token:get', async (event) => {
  // 可选:验证请求来源(如窗口 ID、用户操作状态)
  const window = BrowserWindow.fromWebContents(event.sender);
  if (window && window.isFocused()) { // 简单的合法性校验
    return await keytar.getPassword(SERVICE_NAME, ACCOUNT_NAME);
  }
  throw new Error('非法的 Token 请求');
});

// 2. 预加载脚本 - 暴露安全的 Token 操作方法
contextBridge.exposeInMainWorld('electronAPI', {
  saveToken: (token) => ipcRenderer.invoke('token:save', token),
  getToken: () => ipcRenderer.invoke('token:get')
});

// 3. 渲染进程 - 仅在鉴权时临时获取 Token
async function initAuth() {
  const token = await window.electronAPI.getToken();
  // 仅在当前会话使用,用完立即清空(如存储在内存,不写入 localStorage)
  const authInstance = new AuthFramework(token); // 适配前端鉴权框架
}
方案 3:使用 session 隔离(兜底)

若以上方案无法适配,可将 Token 存储在 Electron 的 session 中(渲染进程无法直接读取,仅请求时自动携带):

javascript 复制代码
// 主进程
const { session } = require('electron');
// 设置 Cookie(HttpOnly + Secure,渲染进程无法通过 JS 读取)
session.defaultSession.cookies.set({
  url: 'https://api.example.com',
  name: 'auth_token',
  value: 'your-secure-token',
  httpOnly: true, // 关键:禁止 JS 读取
  secure: true,   // 仅 HTTPS 请求携带
  sameSite: 'strict'
});

三、额外安全加固措施

  1. 禁用渲染进程的 evalremote:避免代码注入导致敏感信息泄露;

  2. 加密存储敏感数据:即使 Token 存储在文件/密钥库,也要通过 AES 等算法加密;

  3. 限制 IPC 通信的权限:验证 IPC 请求的发送者(如窗口 ID、WebContents ID),拒绝非法请求;

  4. 及时清理 Token:应用退出/用户登出时,立即清空主进程内存中的 Token,并删除存储的 Token;

  5. 启用 Content-Security-Policy (CSP) :在 index.html 中设置 CSP,限制脚本执行来源:

    html 复制代码
    <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self';">

总结

  1. 环境变量安全 :仅通过预加载脚本的 contextBridge 暴露非敏感环境变量,禁用渲染进程的 Node.js 集成和上下文隔离;
  2. 敏感 Token 传递:优先使用"主进程代理 API"方案,避免渲染进程直接接触 Token;若必须传递,使用系统密钥库存储并通过鉴权后的 IPC 临时获取;
  3. 核心安全原则:敏感数据仅保留在主进程,渲染进程仅通过受控的 IPC 接口交互,禁止直接暴露任何敏感信息。

在非 HTTPS(纯 HTTP)环境下,如何安全处理 Electron 中的 session 和敏感 Token 传递

你现在关注的是在非 HTTPS(纯 HTTP)环境下,如何安全处理 Electron 中的 session 和敏感 Token 传递问题,这确实是实际开发中很常见的场景,HTTP 环境下的安全风险会更高,需要针对性调整方案。

一、HTTP 环境下的核心安全风险

首先明确:HTTP 是明文传输协议,任何网络层面的拦截都能获取到传输的数据,所以我们的安全策略核心是:

  1. 尽量让敏感 Token 不出现在网络传输中(主进程代理请求);
  2. 即使必须传输,也要在应用层做加密,同时禁用 HTTP 环境下的不安全配置;
  3. 绝对不能依赖 HTTP 的 Cookie(如 HttpOnly)做安全防护。

二、HTTP 环境下 Session/Token 的安全处理方案

1. 核心方案:主进程代理 API 请求(适配 HTTP)

这依然是最优方案,且在 HTTP 环境下更重要------Token 仅在主进程内存中,不随 HTTP 请求直接暴露(即使 HTTP 被抓包,也抓不到 Token,因为 Token 由主进程添加后再发请求)。

修改适配 HTTP 的完整代码

javascript 复制代码
// 1. 主进程 (main.js) - 代理 HTTP 请求,Token 仅在主进程
const { app, BrowserWindow, ipcMain } = require('electron');
const path = require('path');

let authToken = ''; // Token 仅存主进程内存,不暴露给渲染进程

// 初始化 Token(从安全存储读取,而非网络/渲染进程)
function initToken() {
  // 示例:从加密文件读取,而非 HTTP 响应直接获取
  authToken = 'your-encrypted-token-from-local-storage';
}

// 监听渲染进程的 API 请求(适配 HTTP)
ipcMain.handle('api:request', async (event, options) => {
  try {
    // 主进程拼接 Token 后发起 HTTP 请求
    const response = await fetch(options.url, {
      method: options.method || 'GET',
      headers: {
        'Authorization': `Bearer ${authToken}`, // Token 仅主进程使用
        'Content-Type': 'application/json',
        ...options.headers
      },
      body: options.body ? JSON.stringify(options.body) : null,
      // 禁用 HTTP 重定向(减少劫持风险)
      redirect: 'manual'
    });

    const data = await response.json();
    return { success: true, data };
  } catch (error) {
    return { success: false, error: error.message };
  }
});

function createWindow() {
  const mainWindow = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js'),
      enableRemoteModule: false,
      webSecurity: false, // 仅 HTTP 环境下临时关闭(HTTPS 必须开启)
      allowRunningInsecureContent: true // 允许 HTTP 内容(仅测试/内网环境)
    }
  });
  mainWindow.loadFile('index.html');
  initToken();
}

app.whenReady().then(createWindow);

// 2. 预加载脚本 (preload.js) - 无变化,仅暴露受控接口
const { contextBridge, ipcRenderer } = require('electron');
contextBridge.exposeInMainWorld('electronAPI', {
  requestAPI: (options) => ipcRenderer.invoke('api:request', options)
});

// 3. 渲染进程 (renderer.js) - 调用 HTTP API,无感知 Token
async function fetchData() {
  // 目标地址是 HTTP,渲染进程仅传 URL,不接触 Token
  const result = await window.electronAPI.requestAPI({
    url: 'http://your-api-server.com/user/info',
    method: 'GET'
  });
  if (result.success) {
    console.log('数据:', result.data);
  }
}

你之前提到的 session 设置 Cookie 方案,在 HTTP 环境下完全不可用 ------因为 secure: true 要求 HTTPS,而去掉 secure: true 后,Cookie 会以明文传输,且渲染进程可读取,风险极高。

❌ 绝对不要在 HTTP 环境下用以下代码:

javascript 复制代码
// 危险!HTTP 环境下禁用此写法
session.defaultSession.cookies.set({
  url: 'http://api.example.com',
  name: 'auth_token',
  value: 'your-token',
  httpOnly: true, // HTTP 下 HttpOnly 无法防网络抓包
  secure: false,  // 去掉 secure 后 Cookie 明文传输
  sameSite: 'strict'
});
3. 兜底方案:HTTP 请求加密(应用层加固)

如果你的 HTTP 接口无法修改,且必须让请求携带 Token,可在主进程对请求体/Header 做轻量加密,服务端解密:

javascript 复制代码
// 主进程 - 加密 Token 后再放入 HTTP 请求头
const crypto = require('crypto');

// 加密函数(示例:AES 加密,密钥仅主进程和服务端知晓)
function encryptToken(token) {
  const key = crypto.scryptSync('your-server-shared-secret', 'salt', 32);
  const iv = crypto.randomBytes(16);
  const cipher = crypto.createCipheriv('aes-256-cbc', key, iv);
  let encrypted = cipher.update(token, 'utf8', 'hex');
  encrypted += cipher.final('hex');
  return { encrypted, iv: iv.toString('hex') };
}

// 代理请求时加密 Token
ipcMain.handle('api:request', async (event, options) => {
  const { encrypted, iv } = encryptToken(authToken);
  const response = await fetch(options.url, {
    method: options.method || 'GET',
    headers: {
      'X-Encrypted-Token': encrypted, // 加密后的 Token
      'X-Encrypted-IV': iv,           // 初始化向量
      ...options.headers
    }
  });
  // ... 后续逻辑不变
});
4. Electron Session 的安全配置(HTTP 环境)

即使使用 HTTP,也要对 Electron 的 session 做安全限制,避免额外风险:

javascript 复制代码
// 主进程 - Session 安全配置
const { session } = require('electron');

app.whenReady().then(() => {
  // 禁用第三方 Cookie(减少追踪/劫持风险)
  session.defaultSession.setCookie({
    name: 'disable-third-party-cookies',
    value: '1',
    url: 'http://your-api-server.com'
  });

  // 拦截不安全的跳转/请求
  session.defaultSession.webRequest.onBeforeRequest((details, callback) => {
    // 仅允许访问指定的 HTTP 域名,拒绝其他请求
    const allowedDomains = ['http://your-api-server.com'];
    if (!allowedDomains.some(domain => details.url.startsWith(domain))) {
      callback({ cancel: true }); // 拒绝非法域名请求
    } else {
      callback({ cancel: false });
    }
  });
});

三、HTTP 环境下的额外安全建议

  1. 仅限内网/测试环境使用:HTTP 明文传输的风险无法完全消除,生产环境必须升级到 HTTPS(可配置免费的 Let's Encrypt 证书);
  2. 缩短 Token 有效期:即使 Token 被抓包,也能限制攻击窗口,同时增加刷新 Token 的逻辑;
  3. 验证请求来源 :在 IPC 通信时,验证请求的发送者是合法的渲染进程(如通过 event.sender.webContents.id 校验);
  4. 内存中销毁 Token :用户登出/应用关闭时,立即将主进程中的 authToken 置空,避免内存残留。

总结

  1. 核心方案:HTTP 环境下优先使用「主进程代理 API 请求」,Token 仅保留在主进程内存,不随 HTTP 请求直接暴露;
  2. 禁用危险配置 :绝对不要在 HTTP 下使用 session 设置 Token Cookie(HttpOnly/Secure 失效);
  3. 加固措施:仅限内网使用 HTTP,对请求中的敏感信息做应用层加密,同时限制渲染进程的请求范围。

electron 版本 与 node 版本之间的关系

你想了解 Electron 版本和 Node.js 版本之间的对应关系,这是开发 Electron 应用时的一个关键知识点,直接影响到依赖安装、API 兼容性和应用打包。

一、核心关系:Electron 内置 Node.js

Electron 本质上是"Chromium + Node.js + 原生 API"的组合包,每个 Electron 版本都会内置一个特定版本的 Node.js,二者是强绑定关系------你无法自由选择 Electron 应用运行时的 Node.js 版本,只能使用 Electron 内置的那个版本。

1. 版本绑定的原因
  • Electron 的底层功能(如原生模块、IPC 通信)依赖 Node.js 的 C++ API,不同 Node.js 版本的 API 会有变化,因此 Electron 必须固定 Node.js 版本以保证稳定性;
  • Chromium 的 V8 引擎版本也与 Node.js 版本强关联(Node.js 基于 V8),Electron 需同步三者的 V8 版本。
2. 如何查询对应关系

最权威的方式有 3 种,按优先级排序:

方式 1:官方版本对照表(推荐)

Electron 官方维护了详细的版本对应表,包含「Electron 版本 ↔ Node.js 版本 ↔ Chromium 版本」:

方式 2:命令行查看当前 Electron 的 Node 版本

如果你已安装某个版本的 Electron,可通过以下命令快速查看内置 Node 版本:

bash 复制代码
# 全局安装 electron 后
electron -v  # 查看 Electron 版本
electron -e "console.log(process.versions.node)"  # 查看内置 Node 版本
方式 3:运行时获取版本信息

在 Electron 应用中,可通过 process.versions 对象直接获取所有组件版本:

javascript 复制代码
// 主进程/预加载脚本中执行(渲染进程需通过 contextBridge 暴露)
console.log('Electron 版本:', process.versions.electron);
console.log('Node.js 版本:', process.versions.node);
console.log('Chromium 版本:', process.versions.chrome);
console.log('V8 引擎版本:', process.versions.v8);

二、开发中的关键注意事项

1. 原生模块编译依赖 Node 版本

如果你使用了需要编译的原生模块(如 serialportkeytar),必须保证:

  • 编译时使用的 Node 版本 ≡ Electron 内置的 Node 版本;

  • 推荐使用 electron-rebuild 工具自动适配:

    bash 复制代码
    # 安装依赖后执行
    npx electron-rebuild
2. 版本升级的兼容性风险

升级 Electron 版本时,会同步升级内置的 Node.js 和 Chromium,可能导致:

  • Node.js API 变更(如废弃某些方法、新增特性);
  • Chromium 对前端 API 的支持变化(如 ES 特性、Web API);
  • 原生模块需要重新编译。
3. 长期支持(LTS)版本选择
  • Electron 提供 LTS 版本(支持 18 个月),优先选择 LTS 版本以保证稳定性;
  • LTS 版本的 Node.js 通常也是 LTS 版本(如 Electron 28.x 内置 Node 20.x LTS)。

三、版本选择建议

  1. 新手/稳定需求:选择最新的 Electron LTS 版本(如 28.x、30.x),对应的 Node.js 也是 LTS 版本,兼容性最好;
  2. 需使用新 Node 特性:查看官方对照表,选择内置目标 Node 版本的 Electron 版本(注意避免非 LTS 版本);
  3. 需兼容旧依赖:如果项目依赖的原生模块仅支持旧 Node 版本,需降级 Electron 到对应版本。

总结

  1. 强绑定关系:每个 Electron 版本内置固定的 Node.js 版本,无法手动修改,二者一一对应;
  2. 查询方式 :优先通过官方对照表、electron -e 命令或 process.versions 获取版本对应关系;
  3. 开发关键:原生模块需按 Electron 内置 Node 版本编译,升级 Electron 时要注意 Node/Chromium 兼容性。
相关推荐
崔庆才丨静觅31 分钟前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60611 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了1 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅1 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅2 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅2 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment2 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅3 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊3 小时前
jwt介绍
前端
爱敲代码的小鱼3 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax