Electron调用nodejs的cpp .node扩展【安全】

Electron调用nodejs的cpp .node扩展【安全】

环境:

复制代码
electron: 30.1.1
nodejs: 20.14.0

前言

Electron是一个非常流行的跨平台桌面应用框架,它允许开发者使用Web技术来创建原生应用。然而,当应用需要进行高性能计算或访问系统API时,Web技术可能会成为性能瓶颈。这时,开发者可以选择使用C++来开发底层库,并在Electron中调用这些库,以实现高性能的功能。

在前面的文章中,我们使用禁用 contextIsolation 和启用 nodeIntegration的方式来调用C++扩展,这样会降低应用的安全性。

安全的方式为隔离上下文(contextIsolation: true),通过 ipcMain通信使用主线程处理,contextBridge.exposeInMainWorld开放API接口。这种方式推荐在生产环境使用。

代码

复制代码
$ tree
.
+--- build
|   +--- Release
|   |   +--- addon.node
+--- addon.cpp
+--- binding.gyp
+--- CMakeLists.txt
+--- index.html
+--- index.js
+--- package.json
+--- preload.js
+--- renderer.js

index.html

复制代码
<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8" />
  <title>Hello Electron</title>
  <meta http-equiv="Content-Security-Policy" content="default-src 'self' 'unsafe-inline';">
</head>

<body>
  <p id="version"></p>
  <p id="napi"></p>

  <script src="renderer.js"></script>
</body>

</html>

index.js

复制代码
const { app, BrowserWindow,ipcMain } = require('electron/main');
const path = require('path');
const addon = require(path.join(__dirname, '/build/Release/addon.node'));

const createWindow = () => {
  const win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      // nodeIntegration: true, // not safe
      // contextIsolation: false // not safe
      preload: path.join(__dirname, 'preload.js'), // preload script must absolute path
      contextIsolation: true,
      enableRemoteModule: false
    }
  })

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

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

ipcMain.handle('ipcAddon', async () => {
  return addon.hello();
})

preload.js

复制代码
const { contextBridge, ipcRenderer } = require('electron');

contextBridge.exposeInMainWorld('electronAPI', {
    getVersion: () => { 
       return `electron: ${process.versions.electron}, nodejs: ${process.versions.node}, chrome: ${process.versions.chrome}, v8: ${process.versions.v8}`; 
    },
    getHello: async () => {
        return await ipcRenderer.invoke('ipcAddon');
    }
});

renderer.js

复制代码
window.addEventListener('DOMContentLoaded', async () => {
    let info = window.electronAPI.getVersion();
    document.getElementById("version").innerHTML = info;
    console.log(info);

    info = await window.electronAPI.getHello();
    document.getElementById("napi").innerHTML = info;
    console.log(info);
});

addon.cpp

复制代码
#include <node_api.h>

static napi_value helloMethod(napi_env env, napi_callback_info info)
{
    napi_value result;
    napi_create_string_utf8(env, "hello world from napi", NAPI_AUTO_LENGTH, &result);

    return result;
}

static napi_value Init(napi_env env, napi_value exports)
{
    napi_property_descriptor desc = {"hello", 0, helloMethod, 0, 0, 0, napi_default, 0};

    napi_define_properties(env, exports, 1, &desc);

    return exports;
}

NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)

binding.gyp

复制代码
{
  "targets": [
    {
      "target_name": "addon",
      "sources": [ "addon.cpp" ]
    }
  ]
}

CMakeLists.txt

复制代码
cmake_minimum_required(VERSION 2.8.12)

project(addon)

message(STATUS "operation system is ${CMAKE_SYSTEM}")

add_definitions(-std=c++11)

include_directories(${CMAKE_JS_INC})
include_directories(.)

file(GLOB SOURCE_FILES addon.cpp)

add_library(${PROJECT_NAME} SHARED ${SOURCE_FILES} ${CMAKE_JS_SRC})

set_target_properties(${PROJECT_NAME} PROPERTIES PREFIX "" SUFFIX ".node")

target_link_libraries(${PROJECT_NAME} ${CMAKE_JS_LIB})

package.json

复制代码
{
  "name": "my-electron-app",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "electron ."
  }
}

编译

复制代码
node-gyp configure build

结果

复制代码
electron: 30.1.1, nodejs: 20.14.0, chrome: 124.0.6367.243, v8: 12.4.254.20-electron.0

hello world from napi

License

License under CC BY-NC-ND 4.0: 署名-非商业使用-禁止演绎


Reference:

NULL

相关推荐
xiaobangsky1 小时前
Electron桌面应用下,在拍照、展示pdf等模块时,容易导致应用白屏
javascript·electron
就是我5 小时前
Electron多窗口应用实战
前端·javascript·electron
我怎么能这么帅气5 小时前
从“文件失踪案”说起:Electron 中 getAppPath 和 getPath 的妙用
前端·javascript·electron
濮水大叔8 小时前
你认为Vonajs提供的这些特性会比Nestjs更好用吗?
nodejs·nestjs
集成显卡3 天前
图片压缩工具 | Electron+Vue3+Rsbuild开发桌面应用
前端·javascript·electron·vue
朝阳393 天前
Electron-vite【实战】MD 编辑器 -- 系统菜单(含菜单封装,新建文件,打开文件,打开文件夹,保存文件,退出系统)
electron·编辑器
朝阳394 天前
Electron-vite【实战】MD 编辑器 -- 文件列表(含右键快捷菜单,重命名文件,删除本地文件,打开本地目录等)
electron·编辑器
HCl+NaOH=NaCl+H_2O4 天前
quasar electron mode如何打包无边框桌面应用程序
前端·javascript·electron
屋昂仼4 天前
Electron 桌面程序读取dll动态库
前端·javascript·electron
小和尚敲木头5 天前
electron安装报错处理
前端·javascript·electron