From b0d3245b9dbd3d28d50e7bf927cb3abfdcacc71e Mon Sep 17 00:00:00 2001 From: imbytecat Date: Sat, 24 Jan 2026 03:42:12 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=87=8D=E6=9E=84=E7=A1=AC?= =?UTF-8?q?=E4=BB=B6=E6=8C=87=E7=BA=B9=E6=A8=A1=E5=9D=97=E5=B9=B6=E6=B8=85?= =?UTF-8?q?=E7=90=86=E6=97=A0=E5=85=B3=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 添加 ohash 和 systeminformation 依赖项到项目中 - 将硬件指纹生成模块从工具包移至服务器应用,并统一优化注释中的标点符号为中文全角格式,提升代码注释的可读性与一致性。 - 将硬件指纹获取方法的导入路径从 '@furtherverse/utils/fingerprint' 更新为 '@/lib/fingerprint'。 - 移除对本地 workspace 包 @furtherverse/utils 的依赖并清理相关配置 - 删除未使用的工具包配置文件并移除相关依赖项 - 删除硬件指纹测试文件,移除对 systeminformation 模块的模拟和相关测试用例。 - 移除对 fingerprint 工具函数的导出 - 删除未使用的 tsconfig 配置文件 --- apps/server/package.json | 3 +- .../server/src/lib}/fingerprint.ts | 60 +++--- .../server/api/routers/fingerprint.router.ts | 2 +- bun.lock | 17 +- packages/utils/package.json | 25 --- packages/utils/src/fingerprint.test.ts | 173 ------------------ packages/utils/src/index.ts | 1 - packages/utils/tsconfig.json | 3 - 8 files changed, 35 insertions(+), 249 deletions(-) rename {packages/utils/src => apps/server/src/lib}/fingerprint.ts (74%) delete mode 100644 packages/utils/package.json delete mode 100644 packages/utils/src/fingerprint.test.ts delete mode 100644 packages/utils/src/index.ts delete mode 100644 packages/utils/tsconfig.json diff --git a/apps/server/package.json b/apps/server/package.json index 0567665..9294243 100644 --- a/apps/server/package.json +++ b/apps/server/package.json @@ -15,7 +15,6 @@ "typecheck": "tsc --noEmit" }, "dependencies": { - "@furtherverse/utils": "workspace:*", "@orpc/client": "catalog:", "@orpc/contract": "catalog:", "@orpc/openapi": "catalog:", @@ -30,9 +29,11 @@ "@tauri-apps/api": "catalog:", "drizzle-orm": "catalog:", "drizzle-zod": "catalog:", + "ohash": "catalog:", "postgres": "catalog:", "react": "catalog:", "react-dom": "catalog:", + "systeminformation": "catalog:", "uuid": "catalog:", "zod": "catalog:" }, diff --git a/packages/utils/src/fingerprint.ts b/apps/server/src/lib/fingerprint.ts similarity index 74% rename from packages/utils/src/fingerprint.ts rename to apps/server/src/lib/fingerprint.ts index 96a2ec1..1ebd473 100644 --- a/packages/utils/src/fingerprint.ts +++ b/apps/server/src/lib/fingerprint.ts @@ -3,17 +3,17 @@ import si from 'systeminformation' /** * 硬件指纹质量等级 - * - strong: 2+ 个强标识符可用(推荐用于生产授权) - * - medium: 1 个强标识符可用(可用但不理想) - * - weak: 无强标识符(仅适合开发/测试) + * - strong: 2+ 个强标识符可用(推荐用于生产授权) + * - medium: 1 个强标识符可用(可用但不理想) + * - weak: 无强标识符(仅适合开发/测试) */ export type FingerprintQuality = 'strong' | 'medium' | 'weak' /** - * 标准化的系统信息(用于机器码生成) + * 标准化的系统信息(用于机器码生成) */ export type NormalizedSystemInfo = { - /** 系统 UUID(最稳定的硬件标识符) */ + /** 系统 UUID(最稳定的硬件标识符) */ systemUuid: string | null /** 系统序列号 */ systemSerial: string | null @@ -25,9 +25,9 @@ export type NormalizedSystemInfo = { biosVersion: string | null /** BIOS 供应商 */ biosVendor: string | null - /** CPU 品牌标识(用于质量评估) */ + /** CPU 品牌标识(用于质量评估) */ cpuBrand: string | null - /** 主硬盘序列号(可选,高稳定性) */ + /** 主硬盘序列号(可选,高稳定性) */ primaryDiskSerial?: string | null } @@ -36,14 +36,14 @@ export type NormalizedSystemInfo = { */ export type HardwareFingerprintOptions = { /** - * 缓存 TTL(毫秒),默认 10 分钟 - * 硬件信息变化频率极低,缓存可大幅提升性能 + * 缓存 TTL(毫秒),默认 10 分钟 + * 硬件信息变化频率极低,缓存可大幅提升性能 */ cacheTtlMs?: number /** - * 是否包含主硬盘序列号(默认 true) - * 注意:在容器/虚拟机环境可能获取失败 + * 是否包含主硬盘序列号(默认 true) + * 注意:在容器/虚拟机环境可能获取失败 */ includePrimaryDisk?: boolean } @@ -52,7 +52,7 @@ export type HardwareFingerprintOptions = { * 硬件指纹响应 */ export type HardwareFingerprintResult = { - /** 机器码(HMAC-SHA256 哈希,64 字符十六进制) */ + /** 机器码(HMAC-SHA256 哈希,64 字符十六进制) */ fingerprint: string /** 指纹质量等级 */ quality: FingerprintQuality @@ -91,7 +91,7 @@ function computeQuality(info: NormalizedSystemInfo): { } /** - * 安全地收集标准化系统信息(容错处理) + * 安全地收集标准化系统信息(容错处理) */ async function collectNormalizedInfo( opts: HardwareFingerprintOptions, @@ -115,7 +115,7 @@ async function collectNormalizedInfo( const bios = biosRes.status === 'fulfilled' ? biosRes.value : null const cpu = cpuRes.status === 'fulfilled' ? cpuRes.value : null - // 提取主硬盘序列号(通常是第一个物理磁盘) + // 提取主硬盘序列号(通常是第一个物理磁盘) let primaryDiskSerial: string | null = null if (diskRes.status === 'fulfilled' && Array.isArray(diskRes.value)) { const disks = diskRes.value as Array<{ serialNum?: string; type?: string }> @@ -126,43 +126,43 @@ async function collectNormalizedInfo( } return { - // 系统级标识符(最稳定) + // 系统级标识符(最稳定) systemUuid: (system?.uuid ?? uuid?.hardware ?? null) || null, systemSerial: (system?.serial ?? null) || null, - // 主板标识符(次稳定) + // 主板标识符(次稳定) baseboardSerial: (baseboard?.serial ?? null) || null, baseboardManufacturer: (baseboard?.manufacturer ?? null) || null, - // BIOS 信息(辅助识别) + // BIOS 信息(辅助识别) biosVersion: (bios?.version ?? null) || null, biosVendor: (bios?.vendor ?? null) || null, - // CPU 信息(辅助识别) + // CPU 信息(辅助识别) cpuBrand: (cpu?.brand ?? null) || null, - // 磁盘序列号(可选,高稳定性) + // 磁盘序列号(可选,高稳定性) ...(opts.includePrimaryDisk !== false ? { primaryDiskSerial } : {}), } } /** /** - * 获取硬件指纹(机器码) + * 获取硬件指纹(机器码) * - * 适用场景:客户端部署的软件授权、机器绑定 + * 适用场景:客户端部署的软件授权、机器绑定 * - * 安全说明: - * - 返回 SHA-256 哈希(Base64URL 编码,43 字符),不可逆推原始硬件信息 + * 安全说明: + * - 返回 SHA-256 哈希(Base64URL 编码,43 字符),不可逆推原始硬件信息 * - 使用 ohash 自动处理对象序列化和哈希 - * - 客户端部署场景:客户可以看到代码,无法使用密钥加密 - * - 安全性依赖硬件信息本身的不可伪造性(来自操作系统) + * - 客户端部署场景:客户可以看到代码,无法使用密钥加密 + * - 安全性依赖硬件信息本身的不可伪造性(来自操作系统) * - 自动缓存减少系统调用开销 * - * 稳定性: + * 稳定性: * - 优先使用系统 UUID、序列号等不易变更的标识符 * - 避免网络接口等易变信息 - * - 容错处理,部分信息缺失不影响生成 + * - 容错处理,部分信息缺失不影响生成 * * @example * ```typescript @@ -198,9 +198,9 @@ export async function getHardwareFingerprint( // 计算质量 const { quality, count } = computeQuality(info) - // 使用 ohash 生成指纹(自动序列化 + SHA-256 + Base64URL) + // 使用 ohash 生成指纹(自动序列化 + SHA-256 + Base64URL) const fingerprint = hash({ - v: 1, // 版本号,未来如需变更采集策略可递增 + v: 1, // 版本号,未来如需变更采集策略可递增 info, }) @@ -223,7 +223,7 @@ export async function getHardwareFingerprint( } /** - * 清除指纹缓存(用于测试或强制刷新) + * 清除指纹缓存(用于测试或强制刷新) */ export function clearFingerprintCache(): void { cache = null diff --git a/apps/server/src/server/api/routers/fingerprint.router.ts b/apps/server/src/server/api/routers/fingerprint.router.ts index fbe3c37..7044e07 100644 --- a/apps/server/src/server/api/routers/fingerprint.router.ts +++ b/apps/server/src/server/api/routers/fingerprint.router.ts @@ -1,4 +1,4 @@ -import { getHardwareFingerprint } from '@furtherverse/utils/fingerprint' +import { getHardwareFingerprint } from '@/lib/fingerprint' import { os } from '../server' export const get = os.fingerprint.get.handler(async () => { diff --git a/bun.lock b/bun.lock index 9ee412b..466f380 100644 --- a/bun.lock +++ b/bun.lock @@ -25,7 +25,6 @@ "name": "@furtherverse/server", "version": "1.0.0", "dependencies": { - "@furtherverse/utils": "workspace:*", "@orpc/client": "catalog:", "@orpc/contract": "catalog:", "@orpc/openapi": "catalog:", @@ -40,9 +39,11 @@ "@tauri-apps/api": "catalog:", "drizzle-orm": "catalog:", "drizzle-zod": "catalog:", + "ohash": "catalog:", "postgres": "catalog:", "react": "catalog:", "react-dom": "catalog:", + "systeminformation": "catalog:", "uuid": "catalog:", "zod": "catalog:", }, @@ -71,18 +72,6 @@ "name": "@furtherverse/tsconfig", "version": "1.0.0", }, - "packages/utils": { - "name": "@furtherverse/utils", - "version": "1.0.0", - "dependencies": { - "ohash": "catalog:", - "systeminformation": "catalog:", - }, - "devDependencies": { - "@furtherverse/tsconfig": "workspace:*", - "typescript": "catalog:", - }, - }, }, "catalog": { "@biomejs/biome": "^2.3.11", @@ -262,8 +251,6 @@ "@furtherverse/tsconfig": ["@furtherverse/tsconfig@workspace:packages/tsconfig"], - "@furtherverse/utils": ["@furtherverse/utils@workspace:packages/utils"], - "@jridgewell/gen-mapping": ["@jridgewell/gen-mapping@0.3.13", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA=="], "@jridgewell/remapping": ["@jridgewell/remapping@2.3.5", "", { "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.24" } }, "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ=="], diff --git a/packages/utils/package.json b/packages/utils/package.json deleted file mode 100644 index 4c37a9e..0000000 --- a/packages/utils/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "@furtherverse/utils", - "version": "1.0.0", - "private": true, - "type": "module", - "scripts": { - "fix": "biome check --write", - "typecheck": "tsc --noEmit" - }, - "imports": { - "#*": "./src/*" - }, - "exports": { - ".": "./src/index.ts", - "./*": "./src/*.ts" - }, - "dependencies": { - "ohash": "catalog:", - "systeminformation": "catalog:" - }, - "devDependencies": { - "@furtherverse/tsconfig": "workspace:*", - "typescript": "catalog:" - } -} diff --git a/packages/utils/src/fingerprint.test.ts b/packages/utils/src/fingerprint.test.ts deleted file mode 100644 index 944b3ad..0000000 --- a/packages/utils/src/fingerprint.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { beforeEach, describe, expect, it, mock } from 'bun:test' -import { getHardwareFingerprint } from './fingerprint' - -// Mock systeminformation module -const mockSystemInfo = { - uuid: mock(() => - Promise.resolve({ - os: 'test-os-uuid', - hardware: 'test-hardware-uuid', - }), - ), - baseboard: mock(() => - Promise.resolve({ - manufacturer: 'Test Manufacturer', - model: 'Test Model', - version: '1.0', - serial: 'TEST123', - }), - ), - bios: mock(() => - Promise.resolve({ - vendor: 'Test Vendor', - version: '1.0.0', - releaseDate: '2024-01-01', - }), - ), - system: mock(() => - Promise.resolve({ - manufacturer: 'Test System', - model: 'Test Model', - version: '1.0', - sku: 'TEST-SKU', - }), - ), - diskLayout: mock(() => - Promise.resolve([ - { - device: '/dev/sda', - type: 'SSD', - name: 'Test Disk', - size: 512000000000, - }, - ]), - ), - networkInterfaces: mock(() => - Promise.resolve([ - { - iface: 'eth0', - mac: '00:11:22:33:44:55', - ip4: '192.168.1.1', - }, - ]), - ), -} - -mock.module('systeminformation', () => ({ - default: mockSystemInfo, -})) - -describe('fingerprint', () => { - beforeEach(() => { - // Reset all mocks before each test - mockSystemInfo.uuid.mockClear() - mockSystemInfo.baseboard.mockClear() - mockSystemInfo.bios.mockClear() - mockSystemInfo.system.mockClear() - mockSystemInfo.diskLayout.mockClear() - mockSystemInfo.networkInterfaces.mockClear() - }) - - describe('getHardwareFingerprint', () => { - it('should return a fingerprint hash', async () => { - const fingerprint = await getHardwareFingerprint() - - expect(fingerprint).toBeDefined() - expect(typeof fingerprint).toBe('string') - expect(fingerprint.length).toBeGreaterThan(0) - }) - - it('should call all system information methods', async () => { - await getHardwareFingerprint() - - expect(mockSystemInfo.uuid).toHaveBeenCalledTimes(1) - expect(mockSystemInfo.baseboard).toHaveBeenCalledTimes(1) - expect(mockSystemInfo.bios).toHaveBeenCalledTimes(1) - expect(mockSystemInfo.system).toHaveBeenCalledTimes(1) - expect(mockSystemInfo.diskLayout).toHaveBeenCalledTimes(1) - expect(mockSystemInfo.networkInterfaces).toHaveBeenCalledTimes(1) - }) - - it('should return the same fingerprint for the same system info', async () => { - const fingerprint1 = await getHardwareFingerprint() - const fingerprint2 = await getHardwareFingerprint() - - expect(fingerprint1).toBe(fingerprint2) - }) - - it('should return different fingerprint when system info changes', async () => { - const fingerprint1 = await getHardwareFingerprint() - - // Change mock data - mockSystemInfo.uuid.mockImplementationOnce(() => - Promise.resolve({ - os: 'different-os-uuid', - hardware: 'different-hardware-uuid', - }), - ) - - const fingerprint2 = await getHardwareFingerprint() - - expect(fingerprint1).not.toBe(fingerprint2) - }) - - it('should handle empty system information gracefully', async () => { - // Mock empty responses - mockSystemInfo.uuid.mockImplementationOnce(() => - Promise.resolve({ os: '', hardware: '' }), - ) - mockSystemInfo.baseboard.mockImplementationOnce(() => - Promise.resolve({ - manufacturer: '', - model: '', - version: '', - serial: '', - }), - ) - mockSystemInfo.bios.mockImplementationOnce(() => - Promise.resolve({ vendor: '', version: '', releaseDate: '' }), - ) - mockSystemInfo.system.mockImplementationOnce(() => - Promise.resolve({ manufacturer: '', model: '', version: '', sku: '' }), - ) - mockSystemInfo.diskLayout.mockImplementationOnce(() => - Promise.resolve([]), - ) - mockSystemInfo.networkInterfaces.mockImplementationOnce(() => - Promise.resolve([]), - ) - - const fingerprint = await getHardwareFingerprint() - - expect(fingerprint).toBeDefined() - expect(typeof fingerprint).toBe('string') - }) - - it('should handle partial system information', async () => { - mockSystemInfo.baseboard.mockImplementationOnce(() => - Promise.resolve({ - manufacturer: 'Only Manufacturer', - model: '', - version: '', - serial: '', - }), - ) - - const fingerprint = await getHardwareFingerprint() - - expect(fingerprint).toBeDefined() - expect(typeof fingerprint).toBe('string') - }) - - it('should be deterministic with the same input', async () => { - const results = await Promise.all([ - getHardwareFingerprint(), - getHardwareFingerprint(), - getHardwareFingerprint(), - ]) - - expect(results[0]).toBe(results[1]) - expect(results[1]).toBe(results[2]) - }) - }) -}) diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts deleted file mode 100644 index 9e929a8..0000000 --- a/packages/utils/src/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './fingerprint' diff --git a/packages/utils/tsconfig.json b/packages/utils/tsconfig.json deleted file mode 100644 index 086fbdf..0000000 --- a/packages/utils/tsconfig.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "extends": "@furtherverse/tsconfig/base.json" -}