技术方案_20251019204104.md 25 KB

技术方案文档

一、需求概述

基于客户需求,需要开发一款Windows桌面应用程序,具备以下核心功能:

  • 用户登录与界面管理
  • 内嵌Chrome浏览器自动化
  • Steam Desktop Authenticator交互
  • 防破解与安全保护
  • 自动更新机制
  • 响应式窗口布局

二、技术架构方案

2.1 推荐方案:Electron + React + Puppeteer

技术栈选型

技术组件 选型 理由
桌面框架 Electron 28+ 跨平台、内置Chromium、生态成熟、易于开发
前端框架 React 18 + TypeScript 组件化开发、类型安全、社区活跃
UI组件库 Ant Design / Material-UI 企业级UI组件、开箱即用
浏览器自动化 Puppeteer / Playwright 强大的浏览器控制能力,支持Chrome内核
状态管理 Zustand / Redux Toolkit 轻量级状态管理
进程通信 Electron IPC 主进程与渲染进程通信
打包工具 electron-builder 支持多平台打包、代码签名、自动更新
自动更新 electron-updater 与electron-builder无缝集成
代码保护 ASAR加密 + Webpack混淆 防止代码被轻易反编译

三、核心功能实现方案

3.1 应用架构设计

┌─────────────────────────────────────────┐
│          Electron Main Process          │
│  ┌────────────────────────────────────┐ │
│  │  - 窗口管理 (BrowserWindow)         │ │
│  │  - 自动更新 (electron-updater)      │ │
│  │  - 进程通信 (IPC Main)              │ │
│  │  - 浏览器自动化控制 (Puppeteer)     │ │
│  │  - Steam软件交互                    │ │
│  │  - 本地存储与配置                   │ │
│  └────────────────────────────────────┘ │
└─────────────────────────────────────────┘
              ↕ IPC通信
┌─────────────────────────────────────────┐
│       Electron Renderer Process         │
│  ┌────────────────────────────────────┐ │
│  │  React Application                  │ │
│  │  ┌──────────────────────────────┐  │ │
│  │  │  登录页面                     │  │ │
│  │  └──────────────────────────────┘  │ │
│  │  ┌──────────────────────────────┐  │ │
│  │  │  主界面                       │  │ │
│  │  │  ├─ 顶部栏 (Logo/退出)       │  │ │
│  │  │  ├─ 左侧菜单导航             │  │ │
│  │  │  └─ 右侧多Tab内容区          │  │ │
│  │  └──────────────────────────────┘  │ │
│  └────────────────────────────────────┘ │
└─────────────────────────────────────────┘

3.2 登录与界面管理

实现方案:

// 主进程:创建登录窗口
function createLoginWindow() {
  const loginWindow = new BrowserWindow({
    width: 400,
    height: 500,
    frame: false, // 无边框窗口
    resizable: false,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  });
  
  loginWindow.loadURL('login.html');
}

// 登录成功后创建主窗口
function createMainWindow() {
  const mainWindow = new BrowserWindow({
    width: 1200,
    height: 800,
    minWidth: 1000,
    minHeight: 600,
    webPreferences: {
      nodeIntegration: false,
      contextIsolation: true,
      preload: path.join(__dirname, 'preload.js')
    }
  });
  
  mainWindow.loadURL('index.html');
}

界面布局:

  • 顶部:固定高度(60px),包含Logo、用户信息、退出按钮
  • 左侧:固定宽度(200px),可折叠的菜单导航
  • 右侧:动态Tab页系统,支持多Tab切换和关闭

3.3 内嵌Chrome浏览器自动化

方案A:使用Puppeteer(推荐)

优势:

  • 直接使用Electron内置的Chromium
  • 完整的Chrome DevTools Protocol支持
  • 成熟稳定的API

实现步骤:

  1. 打包Chrome浏览器

    // electron-builder配置
    {
    "extraResources": [
    {
      "from": "node_modules/puppeteer/.local-chromium/",
      "to": "chromium",
      "filter": ["**/*"]
    }
    ]
    }
    
    1. 启动浏览器实例 ```typescript import puppeteer from 'puppeteer-core';

    async function launchBrowser() { const chromePath = path.join( process.resourcesPath, 'chromium', 'chrome.exe' );

    const browser = await puppeteer.launch({ executablePath: chromePath, headless: false, // 可视化浏览器 defaultViewport: null, args: [ '--disable-web-security', '--disable-features=IsolateOrigins,site-per-process' ] });

    return browser; } ```

  2. 自动化操作示例 ```typescript async function automateWebPage(url: string) { const browser = await launchBrowser(); const page = await browser.newPage();

await page.goto(url);

// 填充表单 await page.type('#username', 'user@example.com'); await page.type('#password', 'password123');

// 点击按钮 await page.click('button[type="submit"]');

// 等待导航 await page.waitForNavigation();

// 截图 await page.screenshot({ path: 'screenshot.png' });

await browser.close(); }


#### **方案B:使用Playwright(备选)**

**优势:**
- 支持多浏览器内核
- 更现代的API设计
- 更好的自动等待机制

```typescript
import { chromium } from 'playwright-core';

async function launchPlaywright() {
  const browser = await chromium.launch({
    executablePath: chromePath,
    headless: false
  });
  
  const context = await browser.newContext();
  const page = await context.newPage();
  
  return { browser, page };
}

3.4 Chrome插件支持

实现方案:

  1. 打包插件文件

    // 将插件文件夹放入resources
    {
    "extraResources": [
    {
      "from": "chrome-extensions/",
      "to": "extensions",
      "filter": ["**/*"]
    }
    ]
    }
    
    1. 加载插件 ```typescript const extensionPath = path.join( process.resourcesPath, 'extensions', 'my-extension' );

    const browser = await puppeteer.launch({ headless: false, args: [ --disable-extensions-except=${extensionPath}, --load-extension=${extensionPath} ] }); ```

3.5 Steam Desktop Authenticator 交互

实现方案:

  1. 方案A:进程调用(推荐) ```typescript import { spawn, exec } from 'child_process'; import path from 'path';

// 打包SDA.exe到resources const sdaPath = path.join(process.resourcesPath, 'sda', 'SteamDesktopAuthenticator.exe');

// 调用SDA获取验证码 function getSteamGuardCode(username: string): Promise { return new Promise((resolve, reject) => {

const process = spawn(sdaPath, ['--user', username, '--get-code']);

let output = '';
process.stdout.on('data', (data) => {
  output += data.toString();
});

process.on('close', (code) => {
  if (code === 0) {
    const code = output.trim();
    resolve(code);
  } else {
    reject(new Error('Failed to get Steam Guard code'));
  }
});

}); }

// 确认Steam交易 function confirmSteamTrade(tradeId: string): Promise { return new Promise((resolve, reject) => {

exec(`"${sdaPath}" --confirm-trade ${tradeId}`, (error, stdout) => {
  if (error) {
    reject(error);
  } else {
    resolve(stdout.includes('success'));
  }
});

}); }


2. **方案B:读取SDA配置文件**
```typescript
import fs from 'fs';
import crypto from 'crypto';

// SDA的配置文件通常在用户目录
const sdaConfigPath = path.join(
  process.env.APPDATA,
  'SteamDesktopAuthenticator',
  'maFiles'
);

// 读取账号配置
function readSDAConfig(username: string) {
  const configFile = path.join(sdaConfigPath, `${username}.maFile`);
  const data = fs.readFileSync(configFile, 'utf-8');
  return JSON.parse(data);
}

// 生成验证码(需要实现Steam的TOTP算法)
function generateSteamGuardCode(sharedSecret: string): string {
  // 实现Steam的Time-based OTP算法
  // 参考SDA源码实现
  const time = Math.floor(Date.now() / 1000);
  const timeBuffer = Buffer.allocUnsafe(8);
  timeBuffer.writeBigInt64BE(BigInt(Math.floor(time / 30)));
  
  const hmac = crypto.createHmac('sha1', Buffer.from(sharedSecret, 'base64'));
  hmac.update(timeBuffer);
  const hash = hmac.digest();
  
  // Steam字符集
  const steamChars = '23456789BCDFGHJKMNPQRTVWXY';
  let code = '';
  
  // 生成5位验证码
  const start = hash[19] & 0x0f;
  const fullCode = hash.readUInt32BE(start) & 0x7fffffff;
  
  for (let i = 0; i < 5; i++) {
    code += steamChars[fullCode % steamChars.length];
  }
  
  return code;
}
  1. IPC通信封装 ```typescript // 主进程注册handler ipcMain.handle('steam:getGuardCode', async (event, username) => { try { const code = await getSteamGuardCode(username); return { success: true, code }; } catch (error) { return { success: false, error: error.message }; } });

// 渲染进程调用 const result = await window.electron.steam.getGuardCode('myusername'); if (result.success) { console.log('验证码:', result.code); }


### 3.6 自动更新功能

**实现方案:**

1. **配置electron-updater**
```javascript
// package.json
{
  "build": {
    "publish": [
      {
        "provider": "generic",
        "url": "https://your-server.com/updates"
      }
    ]
  }
}
  1. 主进程实现自动更新 ```typescript import { autoUpdater } from 'electron-updater';

// 配置更新服务器 autoUpdater.setFeedURL({ provider: 'generic', url: 'https://your-server.com/updates' });

// 检查更新 autoUpdater.checkForUpdates();

// 监听更新事件 autoUpdater.on('update-available', (info) => { // 通知渲染进程有新版本 mainWindow.webContents.send('update:available', info); });

autoUpdater.on('update-downloaded', (info) => { // 下载完成,询问用户是否安装 mainWindow.webContents.send('update:downloaded', info); });

// 安装更新 ipcMain.on('update:install', () => { autoUpdater.quitAndInstall(); });


3. **渲染进程UI提示**
```typescript
// React组件
function UpdateNotification() {
  const [updateInfo, setUpdateInfo] = useState(null);
  
  useEffect(() => {
    window.electron.on('update:available', (info) => {
      notification.info({
        message: '发现新版本',
        description: `版本 ${info.version} 正在下载...`
      });
    });
    
    window.electron.on('update:downloaded', (info) => {
      Modal.confirm({
        title: '更新已下载',
        content: '是否立即重启安装新版本?',
        onOk: () => {
          window.electron.send('update:install');
        }
      });
    });
  }, []);
  
  return null;
}

3.7 防破解与代码保护

多层防护方案:

  1. ASAR加密

    // electron-builder配置
    {
    "asar": true,
    "asarUnpack": ["**/*.node", "**/*.exe"],
    "electronDownload": {
    "mirror": "https://npm.taobao.org/mirrors/electron/"
    }
    }
    
    1. 代码混淆(Webpack) ```javascript // webpack.config.js const TerserPlugin = require('terser-webpack-plugin'); const WebpackObfuscator = require('webpack-obfuscator');

    module.exports = { optimization: { minimize: true, minimizer: [ new TerserPlugin({

    terserOptions: {
      compress: {
        drop_console: true,
        drop_debugger: true
      },
      mangle: true
    }
    

    }) ] }, plugins: [ new WebpackObfuscator({ rotateStringArray: true, stringArray: true, stringArrayThreshold: 0.75 }, []) ] }; ```

  2. 敏感代码原生化 ```typescript // 使用Node Native Addon(C++)保护核心逻辑 // 编译为.node二进制文件 const nativeModule = require('./build/Release/protection.node');

function validateLicense(key: string): boolean { return nativeModule.checkLicense(key); }


4. **许可证验证**
```typescript
import crypto from 'crypto';

// 硬件ID绑定
function getHardwareId(): string {
  const os = require('os');
  const cpuId = os.cpus()[0].model;
  const macAddress = Object.values(os.networkInterfaces())
    .flat()
    .find(i => !i.internal && i.mac !== '00:00:00:00:00:00')?.mac;
  
  return crypto
    .createHash('sha256')
    .update(cpuId + macAddress)
    .digest('hex');
}

// 验证许可证
function validateLicense(licenseKey: string): boolean {
  const hardwareId = getHardwareId();
  const serverUrl = 'https://your-server.com/api/validate';
  
  // 向服务器验证
  return fetch(serverUrl, {
    method: 'POST',
    body: JSON.stringify({ licenseKey, hardwareId })
  })
  .then(res => res.json())
  .then(data => data.valid);
}
  1. 代码完整性检查 ```typescript import fs from 'fs'; import crypto from 'crypto';

function verifyIntegrity(): boolean { const appPath = app.getAppPath(); const checksumFile = path.join(appPath, 'checksums.json'); const checksums = JSON.parse(fs.readFileSync(checksumFile, 'utf-8'));

for (const [file, expectedHash] of Object.entries(checksums)) {

const filePath = path.join(appPath, file);
const content = fs.readFileSync(filePath);
const actualHash = crypto.createHash('sha256').update(content).digest('hex');

if (actualHash !== expectedHash) {
  return false; // 文件被篡改
}

}

return true; }

// 应用启动时检查 app.on('ready', () => { if (!verifyIntegrity()) {

dialog.showErrorBox('安全警告', '检测到程序文件被篡改,无法启动!');
app.quit();

} });


### 3.8 窗口大小控制

```typescript
// 主进程:窗口控制API
ipcMain.handle('window:resize', (event, width, height) => {
  const window = BrowserWindow.fromWebContents(event.sender);
  window.setSize(width, height, true);
});

ipcMain.handle('window:maximize', (event) => {
  const window = BrowserWindow.fromWebContents(event.sender);
  if (window.isMaximized()) {
    window.unmaximize();
  } else {
    window.maximize();
  }
});

ipcMain.handle('window:minimize', (event) => {
  const window = BrowserWindow.fromWebContents(event.sender);
  window.minimize();
});

ipcMain.handle('window:setFullScreen', (event, flag) => {
  const window = BrowserWindow.fromWebContents(event.sender);
  window.setFullScreen(flag);
});

// 渲染进程:React组件
function WindowControls() {
  const handleResize = (width: number, height: number) => {
    window.electron.window.resize(width, height);
  };
  
  const handleMaximize = () => {
    window.electron.window.maximize();
  };
  
  return (
    <div className="window-controls">
      <button onClick={() => handleResize(1024, 768)}>标准</button>
      <button onClick={() => handleResize(1280, 720)}>宽屏</button>
      <button onClick={() => handleResize(1920, 1080)}>全高清</button>
      <button onClick={handleMaximize}>最大化</button>
    </div>
  );
}

四、项目结构

buff-app/
├── package.json
├── tsconfig.json
├── webpack.config.js
├── electron-builder.json
├── src/
│   ├── main/                    # 主进程代码
│   │   ├── index.ts             # 主进程入口
│   │   ├── windows.ts           # 窗口管理
│   │   ├── updater.ts           # 自动更新
│   │   ├── browser-automation.ts # 浏览器自动化
│   │   ├── steam-integration.ts  # Steam交互
│   │   ├── ipc-handlers.ts      # IPC处理器
│   │   └── security.ts          # 安全验证
│   ├── preload/                 # 预加载脚本
│   │   └── index.ts
│   ├── renderer/                # 渲染进程(React)
│   │   ├── index.tsx
│   │   ├── App.tsx
│   │   ├── pages/               # 页面组件
│   │   │   ├── Login.tsx
│   │   │   ├── Dashboard.tsx
│   │   │   └── ...
│   │   ├── components/          # 通用组件
│   │   │   ├── Layout/
│   │   │   ├── Header/
│   │   │   ├── Sidebar/
│   │   │   └── TabView/
│   │   ├── store/               # 状态管理
│   │   └── utils/               # 工具函数
│   └── common/                  # 共享代码
│       ├── types.ts
│       └── constants.ts
├── resources/                   # 资源文件
│   ├── chromium/                # Chrome浏览器
│   ├── extensions/              # Chrome插件
│   ├── sda/                     # Steam Desktop Authenticator
│   └── icons/                   # 应用图标
└── dist/                        # 构建输出

五、开发路线图

Phase 1:基础框架搭建(1-2周)

  • 初始化Electron + React项目
  • 配置TypeScript、Webpack、ESLint
  • 实现登录界面与主界面布局
  • 实现左侧菜单导航系统
  • 实现右侧多Tab页系统
  • 窗口大小控制功能

Phase 2:浏览器自动化(2-3周)

  • 集成Puppeteer/Playwright
  • 打包Chrome浏览器到应用
  • 实现基础自动化操作(导航、填表、点击)
  • 实现Chrome插件加载机制
  • 开发自动化任务管理器
  • 实现浏览器窗口与主窗口的通信

Phase 3:Steam集成(1-2周)

  • 集成Steam Desktop Authenticator
  • 实现Steam登录验证码获取
  • 实现Steam交易确认功能
  • 开发Steam账号管理界面
  • 测试各种Steam操作场景

Phase 4:安全与防护(1-2周)

  • 实现ASAR加密
  • 配置代码混淆
  • 开发许可证验证系统
  • 实现硬件ID绑定
  • 代码完整性检查
  • 安全测试与漏洞修复

Phase 5:自动更新与优化(1周)

  • 配置electron-updater
  • 搭建更新服务器
  • 实现增量更新
  • 性能优化
  • 内存泄漏检查

Phase 6:测试与发布(1-2周)

  • Windows 7/8/10/11兼容性测试
  • 功能测试与Bug修复
  • 用户体验优化
  • 打包发布版本
  • 编写用户文档

总开发周期:8-12周


六、技术难点与解决方案

6.1 Chrome浏览器打包体积过大

问题: Chromium完整包约300-500MB

解决方案:

  1. 使用Electron内置Chromium(已包含在应用中)
  2. 仅在需要时下载独立Chrome
  3. 使用压缩算法(LZMA)减小安装包
  4. 提供在线安装版和离线完整版

6.2 Chrome插件兼容性

问题: 某些插件可能不兼容自动化浏览器

解决方案:

  1. 测试常用插件的兼容性
  2. 提供插件白名单机制
  3. 针对关键插件做适配
  4. 提供插件管理界面

6.3 Steam Desktop Authenticator集成

问题: SDA是独立应用,需要进程间通信

解决方案:

  1. 通过命令行参数调用SDA
  2. 读取SDA配置文件自行实现算法
  3. 使用SDA的API(如果有)
  4. 监听SDA的配置文件变化

6.4 防破解难度

问题: Electron应用容易被反编译

解决方案:

  1. 核心算法用C++编写为原生模块
  2. 服务器端验证关键操作
  3. 定期更新加密方式
  4. 硬件绑定 + 在线验证

6.5 自动更新可靠性

问题: 更新失败可能导致应用无法启动

解决方案:

  1. 实现更新前备份
  2. 增量更新减少失败概率
  3. 更新失败自动回滚
  4. 提供手动更新选项

七、部署与分发

7.1 打包配置

{
  "name": "buff-app",
  "version": "1.0.0",
  "build": {
    "appId": "com.yourcompany.buffapp",
    "productName": "Buff App",
    "copyright": "Copyright © 2025",
    "directories": {
      "output": "dist",
      "buildResources": "resources"
    },
    "files": [
      "dist/**/*",
      "package.json"
    ],
    "win": {
      "target": [
        {
          "target": "nsis",
          "arch": ["x64", "ia32"]
        }
      ],
      "icon": "resources/icons/icon.ico",
      "requestedExecutionLevel": "asInvoker"
    },
    "nsis": {
      "oneClick": false,
      "allowToChangeInstallationDirectory": true,
      "perMachine": true,
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "shortcutName": "Buff App"
    },
    "extraResources": [
      {
        "from": "resources/chromium",
        "to": "chromium"
      },
      {
        "from": "resources/extensions",
        "to": "extensions"
      },
      {
        "from": "resources/sda",
        "to": "sda"
      }
    ],
    "publish": {
      "provider": "generic",
      "url": "https://your-server.com/updates"
    }
  }
}

7.2 代码签名

Windows代码签名:

# 获取代码签名证书(EV或OV证书)
# 配置electron-builder
{
  "win": {
    "certificateFile": "cert.pfx",
    "certificatePassword": "your-password",
    "signingHashAlgorithms": ["sha256"],
    "sign": "./sign.js" // 自定义签名脚本
  }
}

7.3 系统要求

最低配置:

  • 操作系统:Windows 7 SP1 / 8 / 10 / 11(32位或64位)
  • CPU:双核处理器 2.0 GHz+
  • 内存:4 GB RAM
  • 硬盘:500 MB 可用空间
  • 网络:互联网连接(用于登录和更新)

推荐配置:

  • 操作系统:Windows 10/11 64位
  • CPU:四核处理器 2.5 GHz+
  • 内存:8 GB RAM
  • 硬盘:1 GB 可用空间
  • 网络:宽带连接

八、成本估算

8.1 开发成本

  • 前端开发:3-4人周
  • 后端/主进程开发:4-5人周
  • 测试与优化:2-3人周
  • 总计:9-12人周

8.2 基础设施成本

  • 代码签名证书:$300-500/年
  • 服务器(更新+API):$20-50/月
  • CDN流量:按使用量
  • 域名:$10-20/年

8.3 第三方服务(可选)

  • 崩溃报告(Sentry):$26/月起
  • 分析统计(Mixpanel):免费-$25/月
  • 日志管理:$10-30/月

九、风险评估

风险项 概率 影响 应对措施
Chrome打包体积过大 高 中 使用Electron内置Chromium或在线下载
SDA集成困难 中 高 预研SDA API,准备备用方案
防破解被突破 中 高 多层防护+服务端验证
Windows版本兼容性 低 中 多版本测试,使用兼容API
自动更新失败 低 中 实现回滚机制,提供手动更新
性能问题 中 中 代码优化,异步处理,懒加载

十、备选方案

方案B:.NET + WPF + CefSharp

技术栈:

  • 框架:.NET 6/7 + WPF
  • 浏览器:CefSharp(基于Chromium)
  • 语言:C#
  • 打包:ClickOnce / Squirrel.Windows

优势:

  • Windows原生性能更好
  • 更容易保护代码(编译为IL,可混淆)
  • 打包体积相对较小
  • .NET生态成熟

劣势:

  • 开发效率低于Electron
  • UI开发不如React灵活
  • 浏览器自动化能力弱于Puppeteer

方案C:Tauri + Rust + React

技术栈:

  • 框架:Tauri 1.x
  • 后端:Rust
  • 前端:React
  • 浏览器:系统WebView

优势:

  • 极小的打包体积(<10MB)
  • 高性能、低内存占用
  • 安全性极高

劣势:

  • 生态相对不成熟
  • 依赖系统WebView(不是Chrome)
  • 学习曲线陡峭(Rust)
  • 浏览器自动化受限

十一、下一步行动

  1. 确认技术方案:与客户讨论并确定最终技术栈
  2. 需求细化:明确每个功能模块的详细需求
  3. 原型设计:设计UI原型,确认交互流程
  4. 项目搭建:初始化代码仓库,配置开发环境
  5. 迭代开发:按照路线图逐步实现功能
  6. 测试验证:持续测试,及时反馈问题

十二、待讨论问题

  1. 登录方式:是否需要账号注册?使用邮箱还是用户名?是否支持第三方登录?
  2. 数据存储:用户数据存储在本地还是云端?是否需要数据同步?
  3. 浏览器操作场景:具体需要自动化哪些网站?需要什么样的操作流程?
  4. Steam功能范围:除了验证码和交易确认,还需要哪些Steam功能?
  5. 许可证模式:永久授权还是订阅制?单机版还是需要在线验证?
  6. 更新频率:预计多久发布一次更新?强制更新还是可选更新?
  7. 用户权限:是否需要多用户系统?是否需要权限分级?
  8. 日志与监控:是否需要记录用户操作日志?是否需要远程监控?

附录

A. 参考资源

B. 相似项目案例

  • Discord(Electron应用)
  • VS Code(Electron应用)
  • Postman(Electron应用)
  • Steam客户端(类似的游戏平台)

文档版本: v1.0
创建日期: 2025-10-19
最后更新: 2025-10-19