代码之家  ›  专栏  ›  技术社区  ›  Ian Wise

如何在没有节点集成的情况下访问节点API

  •  1
  • Ian Wise  · 技术社区  · 7 年前

    nodeIntegration 特权,但是我不希望不受信任的外部内容有这样的特权。不受信任的代码被加载到 webview ,API类通过 preload . 脚本被加载,类被创建,它可以执行我想要的所有功能,而不会出现问题。但问题是,在脚本完成加载后,我希望保留在全局范围内的类将被销毁。这个不受信任的代码访问我的API的唯一方法是如果这个类仍然在全局范围内。 是否可以在预加载的脚本中实例化一个可以访问nodeIntegration的类,并且该类可以被非预加载的脚本文件访问?

    例子:

    预加载脚本:

    var API = function() {
        const fs = remote.require('fs');
    
        API.createFile = function(){
            /*... do stuff with fs here ...*/
        }
    }
    

    非预加载脚本(不受信任的代码)

    var instanceOfAPI = new API();
    
    instanceOfAPI.createFile(); //should work
    fs.writeFile(); //should NOT work
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Ian Wise    7 年前

    将API放在preload脚本下的window变量中。例子:

    var API = function() {
        const fs = remote.require('fs');
    
        API.createFile = function(){
            /*... do stuff with fs here ...*/
        }
    }
    
    window.api = new API();
    

    window.api.createFile() //works
    fs.writeFile() //does not
    
        2
  •  1
  •   Luke H    6 年前

    抄袭我的答案: https://stackoverflow.com/a/57656281/289203

    1. 是否可以在不启用节点集成的情况下使用IPC渲染器?

    这是可能的,但很微妙。这可以通过使用 preload 脚本。

    1. 如果是,我该怎么做,为什么这么多资源会排除这些信息?

    使用 预加载 脚本如下所示。然而, 这是 not considered secure . 大多数现有文档都没有显示最佳安全实践。

    // preload.js
    const electron = require('electron');
    
    process.once('loaded', () => {
      global.ipcRenderer = electron.ipcRenderer;
    });
    
    // main.js
    const {app, BrowserWindow} = require('electron');
    
    app.on('ready', () => {
      // Create the browser window.
      win = new BrowserWindow({
          backgroundColor: '#fff', // always set a bg color to enable font antialiasing!
          webPreferences: {
            preload: path.join(__dirname, './preload.js'),
            nodeIntegration: false,
            enableRemoteModule: false,
            // contextIsolation: true,
            // nativeWindowOpen: true,
            // sandbox: true,
          }
      });
      win.loadURL(`file://${path.join(__dirname, 'index.html')}`);
    

    注意 预加载脚本的路径必须是绝对路径,这也可以 当使用webpack/babel时会变得复杂,因为输出文件可能是不同的路径。

    contextIsolation . 这将使上述方法无法使用,因为您不能再向全局范围添加数据。

    最安全的建议是 addEventListener postMessage

    // preload.js
    const { ipcRenderer } = require('electron');
    
    process.once('loaded', () => {
      window.addEventListener('message', event => {
        // do something with custom event
        const message = event.data;
    
        if (message.myTypeField === 'my-custom-message') {
          ipcRenderer.send('custom-message', message);
        }
      });
    });
    
    // main.js
    const {app, ipcMain, BrowserWindow} = require('electron');
    
    app.on('ready', () => {
      ipcMain.on('message', (event, message) => {
        console.log('got an IPC message', e, message);
      });
    
      // Create the browser window.
      win = new BrowserWindow({
          backgroundColor: '#fff', // always set a bg color to enable font antialiasing!
          webPreferences: {
            preload: path.join(__dirname, './preload.js'),
            nodeIntegration: false,
            enableRemoteModule: false,
            contextIsolation: true,
            sandbox: true,
            // nativeWindowOpen: true,
          }
      });
      win.loadURL(`file://${path.join(__dirname, 'index.html')}`);
    
    // renderer.js
    window.postMessage({
      myTypeField: 'my-custom-message',
      someData: 123,
    });