【问题标题】:Would it be safe to enable nodeIntegration in Electron on a local page that is packaged with the app?在与应用程序一起打包的本地页面上启用 Electron 中的 nodeIntegration 是否安全?
【发布时间】:2019-12-21 14:58:46
【问题描述】:

我在创建自定义窗口控件(如关闭、最小/最大和还原)时遇到问题,但 nodeIntegration 已关闭。我在渲染器的本地 html 文件中创建了按钮

main.js

mainWindow = new BrowserWindow({
    x, y, width, height,
    frame: false,
    show: false,
    webPreferences: { devTools: true }
});

mainWindow.loadURL(url.format({
    protocol: 'file:',
    slashes: true,
    pathname: path.join(__dirname, 'assets', 'index.html')
}));

index.html

<div id='minimize' class='noSelect'>&#xE921;</div>
<div id='maximize' class='noSelect'>&#xE922;</div>
<div id='restore' class='noSelect'>&#xE923;</div>
<div id='close' class='noSelect'>&#xE8BB;</div>

<script type='text/javascript' src='../assets/js/index.js'></script>

默认情况下,nodeIntegration 处于关闭状态,因此index.js 无法访问 Node。但是,我需要能够向按钮添加功能以关闭、最小/最大和恢复窗口。

index.js

const { remote } = require('electron');
const mainWindow = remote.getCurrentWindow();

document.getElementById('close').addEventListener('click', () => {
  mainWindow.close();
});

这不起作用,因为 nodeIntegration 被禁用。在本地页面中启用它是否安全?如果没有,这样做的安全方法是什么?

【问题讨论】:

    标签: javascript node.js electron


    【解决方案1】:

    TL;DR:仅当您从不受信任的来源(即互联网或用户输入)加载和执行代码时,启用 nodeIntegration 才会带来风险。

    如果您完全确定您的应用程序只会运行您创建的代码(并且没有 NodeJS 模块从互联网加载脚本),基本上,启用nodeIntegration 的风险很小。

    但是,如果您允许用户运行代码(即输入然后eval 它),或者您提供插件 API,而您无法控制加载的插件,风险级别会上升,因为NodeJS 允许任何 NodeJS 脚本(例如)操作文件系统。

    另一方面,如果禁用nodeIntegration,则无法与主进程通信或操作BrowserWindow,因此无法创建自定义窗口控件。

    【讨论】:

    • 它只会运行我在 NPM 的几个模块之外放入的代码。不确定这是否是您对模块和插件的意思。用户不会输入要运行的代码,只会输入字符串值。
    • 如果你确定没有一个 NPM 模块会从 Internet 加载代码,那么它是低风险的。
    • 不确定如何检查。它是混合器/客户端节点、ws、dotenv、mongodb 等模块。
    • preload 脚​​本角度怎么样?在不启用 nodeIntegration 的情况下是否可行?
    • 这是一个很好的答案。有关禁用 nodeIntegration 的 IPC 示例,请参阅 stackoverflow.com/a/57656281/289203
    【解决方案2】:

    请记住,在 2021 年,您不需要通过 renderer 进程与 main 进程通信。

    相反,您使用消息传递,如下所示:
    main.js

    const {app, BrowserWindow, ipcMain} = require("electron");
    const path = require("path");
    
    app.whenReady().then(open_window);
    
    function open_window() {
      // Explain: Create app window.
      const appWin = new BrowserWindow({
        width: 800,
        height: 600,
        opacity: 0.5,
        webPreferences: {
          preload: path.join(__dirname, "preload.js"),
        },
    
      // Explain: Render the app.
      void minisWindow.loadFile("index.html");
      
      // Spec: User can hide App window by clicking the button.
      ipcMain.on("hide-me", () => appWin.minimize());
      
      // Spec-start: When User focuses App window - it becomes fully opaque.
      ipcMain.on("make-window-opaque", () => appWin.setOpacity(1));
      appWin.on("show", () => minisWindow.setOpacity(1));
      appWin.on("blur", () => minisWindow.setOpacity(0.5));
      // Spec-end.
    }
    
    

    preload.js

    const {ipcRenderer} = require("electron");
    
    // All of the Node.js APIs are available in the preload process.
    // It has the same sandbox as a Chrome extension.
    window.addEventListener("DOMContentLoaded", () => {
      // Spec: User can hide App window by clicking the button.
      document.querySelector("#hideBtn").addEventListener("click", 
        () => ipcRenderer.send("hide-me"));
      });
    
      // Spec: When User focuses App window - it becomes fully opaque.
      document.body.addEventListener("click", () => ipcRenderer.send("make-window-opaque"));
    });
    
    

    这个例子说明了消息传递的两个实例:

    1. 当用户单击 #hideBtn 按钮时 - 发送一条消息,指示 main 隐藏窗口。
    2. 默认情况下窗口是半透明的;当用户点击窗口时(本质上,激活body 上的clickz 事件) - 发送一条消息,指示main 使窗口完全不透明。

    【讨论】:

    • 恕我直言,这不是一个好习惯。您现在在 preload.js 中承担了属于渲染器(处理 onClick)的责任。应该使用 contextBridge 将 api 公开到渲染器中。渲染器处理onClick,调用contextBridge提供的api,preload/main执行不安全代码。
    • 这是个人对架构的偏好。例如,我不喜欢依赖像window.electon 这样的全局变量。我也失去了来自requireing 对象的所有基于类型的好东西。
    • 我正在使用 typescript 并将类型添加到 contextBridge 提供的 api 中。
    • 哦,太好了!您能否发送一个链接,我可以在其中阅读如何将 TS 添加到 Electron?
    • 我从这里得到了打字的想法:github.com/frederiksen/angular-electron-boilerplate。见 src/window-interface/index.d.ts
    猜你喜欢
    • 2023-03-22
    • 2019-11-07
    • 2016-08-26
    • 2016-12-13
    • 1970-01-01
    • 2018-02-13
    • 1970-01-01
    • 2017-08-31
    • 2020-09-04
    相关资源
    最近更新 更多