跳至主要内容

GST Licensing 機台綁定指南

本文件說明 GST.Core.Licensing 的架構、Machine Fingerprint 機制與部署流程。

1. 架構總覽

┌──────────────────────────────────────────────────┐
│ Metalama Aspect │
│ [LicenseCheck] / [LicenseRequired("feature")] │
├──────────────────────────────────────────────────┤
│ ILicenseService │
│ 驗證、Feature 檢查、USB Dongle、背景監控 │
├──────────────────────────────────────────────────┤
│ IReactorLicenseProvider │
│ .NET Reactor License.Status 封裝 │
├──────────────────────────────────────────────────┤
│ Hardware 層 │
│ MachineInfoService(WMI Fingerprint) │
│ UsbDeviceService(USB Dongle 偵測) │
└──────────────────────────────────────────────────┘

2. 核心介面

2.1 ILicenseService

public interface ILicenseService
{
ILicenseInfo? CurrentLicense { get; }
bool IsLicenseValid();
bool IsFeatureEnabled(string featureCode);
bool IsAnyFeatureEnabled(params string[] featureCodes);
IReadOnlyList<string> GetEnabledFeatures();
int? GetLimit(string limitCode);
bool IsUsbDonglePresent();
Task<LicenseActivationResult> ActivateAsync(string licenseKey);
Task<bool> DeactivateAsync();
}

2.2 ILicenseInfo

public interface ILicenseInfo
{
string LicenseId { get; }
string CustomerName { get; }
LicenseTier Tier { get; } // Trial/Basic/Standard/Professional/Enterprise
DateTime ExpiresAt { get; }
int DaysRemaining { get; }
bool IsExpired { get; }
bool IsTrial { get; }
LicenseBindingMode BindingMode { get; }
}

2.3 LicenseBindingMode

[Flags]
public enum LicenseBindingMode
{
None = 0,
Machine = 1, // 綁定硬體 Fingerprint
UsbDongle = 2, // 綁定 USB Dongle
MachineOrUsb = 3, // 擇一(彈性)
MachineAndUsb = 4, // 兩者都需要(嚴格)
Online = 8 // 需線上驗證
}

3. Machine Fingerprint

3.1 組成

元件WMI Query範例
CPU IDWin32_Processor.ProcessorIdBFEBFBFF000A0653
Motherboard SerialWin32_BaseBoard.SerialNumberDBBGV1100120700A379100
BIOS SerialWin32_BIOS.SerialNumberUDBGXTA00K221008170001
HDD SerialWin32_DiskDrive.SerialNumber(Index=0)0000_0000_...
MAC AddressNetworkInterface.GetPhysicalAddress()(最高速非 Loopback)2C-0D-A7-B4-3B-FB

3.2 Combined Hash

CombinedHash = SHA256(UTF8("{CpuId}|{MotherboardSerial}|{BiosSerial}|{HddSerial}"))

僅非空元件參與 Hash 計算。

3.3 容錯機制

public bool Matches(MachineFingerprint other, int tolerance = 1)

預設容許 1 個元件不符,處理硬體更換(如換網卡、換硬碟)的情境。

4. USB Dongle 支援

4.1 偵測方式

Win32_DiskDrive (InterfaceType='USB')
→ Win32_DiskDriveToDiskPartition
→ Win32_LogicalDiskToPartition
→ 取得 DriveLetter, SerialNumber, VID/PID

4.2 UsbDeviceInfo

public record UsbDeviceInfo
{
public required string DeviceId { get; init; }
public required string SerialNumber { get; init; }
public string VolumeLabel { get; init; }
public string DriveLetter { get; init; }
public string VendorId { get; init; } // USB VID
public string ProductId { get; init; } // USB PID
}

5. Metalama Aspect 整合

5.1 [LicenseCheck] — 驗證 License 存在

[LicenseCheck]
public void PerformCriticalOperation() { /* ... */ }
// 無有效 License → 拋出 LicenseException

[LicenseCheck(ThrowOnFailure = false)]
public void PerformOptionalOperation() { /* ... */ }
// 無有效 License → 回傳 default,不拋例外

5.2 [LicenseRequired] — 驗證特定 Feature

[LicenseRequired("AdvancedReporting")]
public Report GenerateAdvancedReport() { /* ... */ }
// Feature 未啟用 → 拋出 LicenseException

6. DI 註冊

services.AddLicensing(options =>
{
options.LicenseFilePath = Path.Combine(configDir, "license.lic");
options.ThrowOnLicenseFailure = false;
options.BackgroundCheckIntervalMinutes = 30;
options.FingerprintTolerance = 1; // 容許 1 個硬體元件不符
options.AllowOfflineMode = true; // 支援離線環境
});

7. 部署流程

7.1 全新部署

1. 在目標機台執行應用程式
└→ 應用程式偵測無 License
└→ 匯出 hardware-id.txt(含 CombinedHash)

2. 使用者將 hardware-id.txt 傳給開發團隊

3. 開發團隊使用 .NET Reactor License Manager 產生 license.lic
└→ 綁定該機台的 Hardware ID

4. 將 license.lic 放到 %APPDATA%\{AppName}\license.lic

5. 重新啟動應用程式 → 驗證通過

7.2 License 檔案位置

%APPDATA%\ProcessVision\license.lic

7.3 App.xaml.cs 載入順序

// 1. 複製 License 檔(在 DI 之前,Reactor 保護 DLL 載入前)
CopyLicenseFiles();

// 2. DI 註冊 AddLicensing()

// 3. 初始化 AspectServiceLocator(啟用 Aspect 注入)
AspectServiceLocator.Initialize(Services);

// 4. 驗證 License 狀態
CheckLicenseStatus();

// 5. 若無 License,匯出 Hardware ID
ExportHardwareId();

8. Debug vs Release 行為

情境DebugRelease
無 License靜默允許所有功能顯示倒數視窗 / 限制功能
ValidatorDevelopmentLicenseValidator(全通過)LicenseValidator(Reactor 驗證)
Feature Check全部 enabled依 License KeyValue 判斷

9. .NET Reactor Hardware Lock 差異

GST.Core.Licensing.NET Reactor Hardware Lock
層級應用層DLL 保護層
綁定方式SHA256 FingerprintReactor 內建 HID
容錯支援(tolerance 參數)不支援
Feature 控制支援(KeyValue)不支援
用途應用授權管理防止 DLL 複製執行

兩者是獨立機制,可同時使用。

10. 常見問題

10.1 License 驗證失敗

  1. 確認 license.lic 在正確路徑(%APPDATA%\{AppName}\
  2. 確認 License 未過期
  3. 確認硬體未大幅更換(超過 tolerance 容許)
  4. 檢查 hardware-id.txt 是否與 License 對應

10.2 硬體更換後 License 失效

更換超過 1 個硬體元件(如同時換主機板 + 硬碟)會導致 Fingerprint 不符。需重新匯出 Hardware ID 並產生新 License。

10.3 離線環境(Air-Gapped)

ValidateOnlineAsync() 目前回傳 true(不需網路),專為工廠離線環境設計。


文件版本:v1.0 | 建立日期:2026-03-16 | 對應 Issue:GST-172