电子 require() 未定义

新手上路,请多包涵

我正在为自己的目的创建一个 Electron 应用程序。我的问题是当我在我的 HTML 页面中使用节点函数时,它会引发以下错误:

‘require()’ 未定义。

有没有办法在我的所有 HTML 页面中使用节点功能?如果可能的话,请给我一个如何做到这一点的例子或提供一个链接。以下是我试图在我的 HTML 页面中使用的变量:

   var app = require('electron').remote;
  var dialog = app.dialog;
  var fs = require('fs');

这些是我在 Electron 中的所有 HTML 窗口中使用的值。

原文由 Mari Selvan 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 620
2 个回答

从版本 5 开始, nodeIntegration 的默认值从 true 更改为 false。您可以在创建浏览器窗口时启用它:

 app.on('ready', () => {
    mainWindow = new BrowserWindow({
        webPreferences: {
            nodeIntegration: true,
            contextIsolation: false,
        }
    });
});

原文由 Sathiraumesh 发布,翻译遵循 CC BY-SA 4.0 许可协议

编辑 2022


我已经 发表了一篇关于 Electron 历史的更大的文章,它的安全性提供了关于影响不同框架版本如何处理安全性的变化的额外上下文(以及最好的方法是什么)。

原答案


我希望这个答案得到一些关注,因为这里的 大部分 答案都会在您的电子应用程序中留下 巨大 的安全漏洞。事实上 ,这个答案 本质上是你应该做的,以便在你的电子应用程序中使用 require() 。 (只有一个新的 electron API 使它在 v7 中更干净一些)。

我在 github 中使用最新的 electron api 写了一个 详细的解释/解决方案,你可以如何 require() 一些东西,但我将在这里简要解释为什么你应该遵循使用预加载脚本、contextBridge 和 ipc 的方法。

问题

电子应用程序很棒,因为我们开始使用节点,但这种力量是一把双刃剑。如果我们不小心,我们就会让某人通过我们的应用程序访问节点,而使用节点的坏人可能会破坏您的机器或删除您的操作系统文件(我想还有其他事情)。

正如@raddevus 在评论中提出的那样,这在加载 远程 内容时是 必需 的。如果您的电子应用程序完全 离线/ _本地_,那么您只需打开 nodeIntegration:true 就可以了。但是,我仍然会选择保留 nodeIntegration:false 作为意外/恶意用户使用你的应用程序的保护措施,并防止任何可能安装在你的机器上的恶意软件与你的电子应用程序交互,使用 nodeIntegration:true 攻击向量(非常罕见,但有可能发生)!

问题是什么样的

当您(以下任何一项)执行以下操作时,就会出现此问题:

  1. 启用 nodeIntegration:true
  2. 使用 remote 模块

所有这些问题都使您可以从渲染器进程 不间断地 访问节点。如果您的渲染器进程曾经被劫持,您可以认为一切都已丢失。

我们的解决方案是什么

解决方案是不让渲染器 直接 访问节点(即 require() ),而是让我们的电子主进程访问 require ,并且任何时候我们的渲染器进程需要使用 require ,将请求编组到主进程。

这在最新版本(7+)的 Electron 中的工作方式是在渲染器端我们设置 ipcRenderer 绑定,在主端我们设置 ipcMain 绑定。在 ipcMain 绑定中,我们设置了使用模块的侦听器方法 require() 。这很好,因为我们的主进程可以 require 它想要的一切。

我们使用 contextBridge 将 ipcRenderer 绑定传递给我们的应用程序代码(以供使用),因此当我们的应用程序需要使用 require d 主模块时,它通过 IPC 发送消息(进程间-通信)和主进程运行一些代码,然后我们发送一条消息返回我们的结果。

_大致来说_,这就是您想要做的。

主程序

const {
  app,
  BrowserWindow,
  ipcMain
} = require("electron");
const path = require("path");
const fs = require("fs");

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

async function createWindow() {

  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: false, // is default value after Electron v5
      contextIsolation: true, // protect against prototype pollution
      enableRemoteModule: false, // turn off remote
      preload: path.join(__dirname, "preload.js") // use a preload script
    }
  });

  // Load app
  win.loadFile(path.join(__dirname, "dist/index.html"));

  // rest of code..
}

app.on("ready", createWindow);

ipcMain.on("toMain", (event, args) => {
  fs.readFile("path/to/file", (error, data) => {
    // Do something with file contents

    // Send result back to renderer process
    win.webContents.send("fromMain", responseObj);
  });
});

预加载.js

 const {
    contextBridge,
    ipcRenderer
} = require("electron");

// Expose protected methods that allow the renderer process to use
// the ipcRenderer without exposing the entire object
contextBridge.exposeInMainWorld(
    "api", {
        send: (channel, data) => {
            // whitelist channels
            let validChannels = ["toMain"];
            if (validChannels.includes(channel)) {
                ipcRenderer.send(channel, data);
            }
        },
        receive: (channel, func) => {
            let validChannels = ["fromMain"];
            if (validChannels.includes(channel)) {
                // Deliberately strip event as it includes `sender`
                ipcRenderer.on(channel, (event, ...args) => func(...args));
            }
        }
    }
);

索引.html

 <!doctype html>
<html lang="en-US">
<head>
    <meta charset="utf-8"/>
    <title>Title</title>
</head>
<body>
    <script>
        window.api.receive("fromMain", (data) => {
            console.log(`Received ${data} from main process`);
        });
        window.api.send("toMain", "some data");
    </script>
</body>
</html>

免责声明

我是 secure-electron-template 的作者,这是一个用于构建电子应用程序的安全模板。我关心这个话题,并且已经为此工作了几周(此时)。

原文由 reZach 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题