为 Electron 应用程序对服务器进行 API 调用的最佳方法

问题描述 投票:0回答:1

我正在开发一个 Electron 应用程序(使用 TypeScript、Vite 和 React),允许用户(公司员工)管理存储在服务器数据库中的客户端和文档。应用程序应与服务器通信,向服务器 API 发送 HTTP 请求。我的计划是在 Electron 应用程序中创建一个本地 API,用于发送 HTTP 请求(带有必要的身份验证令牌)。例如,API 将具有

signIn(email, password)
getClient(clientId)
等函数。

我的第一个问题是,我将该 API 放在哪里?在主进程中还是在渲染器进程(浏览器窗口)中?该应用程序需要安全,但我也不希望代码变得混乱。

为了找到答案,我查看了其他 Electron 应用程序,发现 GitHub Dekstop(使用 Electron)有一个 API(位于

app/src/lib/api.ts
),可以通过 HTTP 请求与 GitHub API 进行通信。这基本上就是我想做的。分析代码后,在我看来,这个API代码是在渲染器进程上运行的。但是,它还在渲染器进程中使用 Node 包,并将
nodeIntegration
设置为
true
Electron 文档 指出:

最重要的是,您不要在任何加载远程内容的渲染器

BrowserWindow
WebContentsView
<webview>中启用 Node.js 集成。

它特别指出不要将其用于远程加载的内容。 GitHub 和我的应用程序都使用本地 HTML 文件。那么,在我的应用程序中使用 Node.js 集成(并因此使用 API 的渲染器进程)是否安全?或者我应该在主进程上创建 API(使用 HTTP 请求)并使用 IPC 在渲染器和主进程之间进行通信?

node.js electron
1个回答
0
投票

如果我必须与外部服务器通信或发出

HTTP
请求,我会这样做。

我使用

main process
进行
API
通话,使用
IPC
进行沟通。

如果您在渲染器进程中启用

Nodejs integration
,您的应用程序将面临漏洞。例如:攻击者可以运行脚本并可以访问 nodejs api 并窃取令牌或任何敏感数据。

如果您使用主流程,则不会将您的 api 暴露给 UI。并且您可以通过 IPC 在渲染器和主进程之间安全地进行通信。

例如:

在我的

main.js
文件中,我这样做:

import { app, BrowserWindow, ipcMain } from 'electron';
import axios from 'axios';

//handle signIn
async function signIn(email, password) {
  const response = await axios.post('https://api.com/signin', { email, password });
  return response.data;
}

//handle API request with IPC
function createWindow() {
  const win = new BrowserWindow({
    webPreferences: {
      preload: path.join(__dirname, 'preload.js'), //IPC communication
    }
  });

  ipcMain.handle('signIn', async (event, email, password) => {
    return await signIn(email, password);
  });
}

app.whenReady().then(createWindow);

我并不完全这样做,但你明白我的意思吗?

在我的

preload.js
文件中:

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

contextBridge.exposeInMainWorld('api', {
  signIn: (email, password) => ipcRenderer.invoke('signIn', email, password),
  //you can also use your other functions here
  //for eg: getClient, checkIfUserExists, etc
});

并且在

signIn.js
或渲染器进程中:

import React, { useState } from 'react';

function SignIn() {
  const [email, setEmail] = useState('');
  const [password, setPassword] = useState('');

  const handleSignIn = async () => {
    try {
      const response = await window.api.signIn(email, password);
      console.log(response);
    } catch (error) {
      console.error(error);
    }
  };

  return (
    <div>
      <input type="email" value={email} onChange={e => setEmail(e.target.value)} />
      <input type="password" value={password} onChange={e => setPassword(e.target.value)} />
      <button onClick={() => handleSignIn()}>Sign In</button>
    </div>
  );
}

export default SignIn;

我希望你明白我想说的。

希望这有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.