Files
Claude Project Manager 0d7d888502 Initial commit
2025-07-05 17:51:16 +02:00

534 Zeilen
18 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
namespace LicenseClient
{
/// <summary>
/// Vollständige Lizenzserver-Integration für .NET-Anwendungen
/// </summary>
public class LicenseManager : IDisposable
{
private readonly HttpClient httpClient;
private readonly string apiKey;
private readonly string appVersion;
private readonly string serverUrl = "https://api-software-undso.z5m7q9dk3ah2v1plx6ju.com";
private readonly string cacheFilePath;
private string licenseKey;
private int? activationId;
private DateTime? expiresAt;
private bool isValid;
private Timer heartbeatTimer;
private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1, 1);
public LicenseManager(string apiKey, string appVersion = "1.0.0")
{
this.apiKey = apiKey;
this.appVersion = appVersion;
// HttpClient Setup
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true // Für Entwicklung
};
httpClient = new HttpClient(handler);
httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
httpClient.Timeout = TimeSpan.FromSeconds(30);
// Cache-Verzeichnis
string appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string appFolder = Path.Combine(appDataPath, "MyApp", "License");
Directory.CreateDirectory(appFolder);
cacheFilePath = Path.Combine(appFolder, "license.json");
}
/// <summary>
/// Eindeutige Maschinen-ID generieren
/// </summary>
private string GetMachineId()
{
try
{
// CPU-ID abrufen
string cpuId = "";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT ProcessorId FROM Win32_Processor"))
{
foreach (ManagementObject obj in searcher.Get())
{
cpuId = obj["ProcessorId"]?.ToString() ?? "";
break;
}
}
// Motherboard Serial Number
string motherboardId = "";
using (ManagementObjectSearcher searcher = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard"))
{
foreach (ManagementObject obj in searcher.Get())
{
motherboardId = obj["SerialNumber"]?.ToString() ?? "";
break;
}
}
return $"{cpuId}-{motherboardId}";
}
catch
{
// Fallback: Machine Name + User
return $"{Environment.MachineName}-{Environment.UserName}";
}
}
/// <summary>
/// Hardware-Fingerprint erstellen
/// </summary>
private string GetHardwareHash()
{
var components = new List<string>
{
GetMachineId(),
Environment.MachineName,
Environment.OSVersion.ToString(),
Environment.ProcessorCount.ToString()
};
// MAC-Adressen hinzufügen
try
{
using (var searcher = new ManagementObjectSearcher("SELECT MACAddress FROM Win32_NetworkAdapter WHERE MACAddress IS NOT NULL"))
{
foreach (ManagementObject obj in searcher.Get())
{
string mac = obj["MACAddress"]?.ToString();
if (!string.IsNullOrEmpty(mac))
components.Add(mac);
}
}
}
catch { }
string combined = string.Join("-", components);
using (SHA256 sha256 = SHA256.Create())
{
byte[] hashBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(combined));
return BitConverter.ToString(hashBytes).Replace("-", "").ToLowerInvariant();
}
}
/// <summary>
/// Lizenz-Cache speichern
/// </summary>
private async Task SaveLicenseCacheAsync()
{
var cacheData = new
{
license_key = licenseKey,
activation_id = activationId,
expires_at = expiresAt?.ToString("O"),
hardware_hash = GetHardwareHash(),
last_verified = DateTime.UtcNow.ToString("O")
};
string json = JsonSerializer.Serialize(cacheData, new JsonSerializerOptions { WriteIndented = true });
await File.WriteAllTextAsync(cacheFilePath, json);
}
/// <summary>
/// Lizenz-Cache laden
/// </summary>
private async Task<LicenseCache> LoadLicenseCacheAsync()
{
if (!File.Exists(cacheFilePath))
return null;
try
{
string json = await File.ReadAllTextAsync(cacheFilePath);
return JsonSerializer.Deserialize<LicenseCache>(json);
}
catch
{
return null;
}
}
/// <summary>
/// Lizenz aktivieren
/// </summary>
public async Task<(bool Success, string Message)> ActivateLicenseAsync(string licenseKey)
{
await semaphore.WaitAsync();
try
{
var requestData = new
{
license_key = licenseKey,
machine_id = GetMachineId(),
hardware_hash = GetHardwareHash(),
os_info = new
{
os = "Windows",
version = Environment.OSVersion.Version.ToString(),
platform = Environment.OSVersion.Platform.ToString(),
service_pack = Environment.OSVersion.ServicePack
},
app_version = appVersion
};
var json = JsonSerializer.Serialize(requestData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync($"{serverUrl}/api/license/activate", content);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var result = JsonSerializer.Deserialize<ActivationResponse>(responseContent);
if (result.success)
{
this.licenseKey = licenseKey;
this.activationId = result.activation_id;
this.isValid = true;
if (!string.IsNullOrEmpty(result.expires_at))
this.expiresAt = DateTime.Parse(result.expires_at);
await SaveLicenseCacheAsync();
StartHeartbeat();
return (true, result.message ?? "Lizenz erfolgreich aktiviert");
}
else
{
return (false, result.message ?? "Aktivierung fehlgeschlagen");
}
}
else
{
return (false, $"Server-Fehler: {response.StatusCode}");
}
}
catch (HttpRequestException ex)
{
return (false, $"Verbindungsfehler: {ex.Message}");
}
catch (Exception ex)
{
return (false, $"Fehler: {ex.Message}");
}
finally
{
semaphore.Release();
}
}
/// <summary>
/// Lizenz verifizieren (Heartbeat)
/// </summary>
public async Task<(bool Valid, string Message)> VerifyLicenseAsync()
{
if (string.IsNullOrEmpty(licenseKey) || !activationId.HasValue)
return (false, "Keine aktive Lizenz");
await semaphore.WaitAsync();
try
{
var requestData = new
{
license_key = licenseKey,
machine_id = GetMachineId(),
hardware_hash = GetHardwareHash(),
activation_id = activationId.Value
};
var json = JsonSerializer.Serialize(requestData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync($"{serverUrl}/api/license/verify", content);
var responseContent = await response.Content.ReadAsStringAsync();
if (response.IsSuccessStatusCode)
{
var result = JsonSerializer.Deserialize<VerificationResponse>(responseContent);
isValid = result.valid;
if (isValid)
{
await SaveLicenseCacheAsync();
if (result.requires_update)
{
OnUpdateAvailable?.Invoke(result.update_url);
}
}
return (isValid, result.message ?? "");
}
else
{
return (false, $"Server-Fehler: {response.StatusCode}");
}
}
catch (HttpRequestException)
{
// Offline-Verifizierung
return await VerifyOfflineAsync();
}
catch (Exception ex)
{
return (false, $"Fehler: {ex.Message}");
}
finally
{
semaphore.Release();
}
}
/// <summary>
/// Offline-Verifizierung mit Grace Period
/// </summary>
private async Task<(bool Valid, string Message)> VerifyOfflineAsync()
{
var cache = await LoadLicenseCacheAsync();
if (cache == null)
return (false, "Keine gecachte Lizenz vorhanden");
// Hardware-Hash prüfen
if (cache.hardware_hash != GetHardwareHash())
{
// Grace Period bei Hardware-Änderung
var lastVerified = DateTime.Parse(cache.last_verified);
var gracePeriod = TimeSpan.FromDays(7);
if (DateTime.UtcNow - lastVerified > gracePeriod)
return (false, "Hardware geändert - Grace Period abgelaufen");
}
// Ablaufdatum prüfen
if (!string.IsNullOrEmpty(cache.expires_at))
{
var expiresAt = DateTime.Parse(cache.expires_at);
if (DateTime.UtcNow > expiresAt)
return (false, "Lizenz abgelaufen");
}
licenseKey = cache.license_key;
activationId = cache.activation_id;
isValid = true;
return (true, "Offline-Modus (gecachte Lizenz)");
}
/// <summary>
/// Nach Updates suchen
/// </summary>
public async Task<UpdateInfo> CheckForUpdatesAsync()
{
if (string.IsNullOrEmpty(licenseKey))
return null;
try
{
var requestData = new
{
current_version = appVersion,
license_key = licenseKey
};
var json = JsonSerializer.Serialize(requestData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PostAsync($"{serverUrl}/api/version/check", content);
if (response.IsSuccessStatusCode)
{
var responseContent = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize<UpdateInfo>(responseContent);
}
}
catch { }
return null;
}
/// <summary>
/// Heartbeat starten
/// </summary>
private void StartHeartbeat()
{
heartbeatTimer?.Dispose();
// Alle 15 Minuten
heartbeatTimer = new Timer(async _ =>
{
var (valid, message) = await VerifyLicenseAsync();
if (!valid)
{
OnLicenseInvalid?.Invoke(message);
}
}, null, TimeSpan.FromMinutes(15), TimeSpan.FromMinutes(15));
}
/// <summary>
/// Lizenz-Informationen abrufen
/// </summary>
public LicenseInfo GetLicenseInfo()
{
return new LicenseInfo
{
IsValid = isValid,
LicenseKey = string.IsNullOrEmpty(licenseKey) ? null : licenseKey.Substring(0, 4) + "****",
ExpiresAt = expiresAt,
MachineId = GetMachineId()
};
}
// Events
public event Action<string> OnUpdateAvailable;
public event Action<string> OnLicenseInvalid;
public void Dispose()
{
heartbeatTimer?.Dispose();
httpClient?.Dispose();
semaphore?.Dispose();
}
}
// Hilfsklassen
public class LicenseCache
{
public string license_key { get; set; }
public int? activation_id { get; set; }
public string expires_at { get; set; }
public string hardware_hash { get; set; }
public string last_verified { get; set; }
}
public class ActivationResponse
{
public bool success { get; set; }
public string message { get; set; }
public int? activation_id { get; set; }
public string expires_at { get; set; }
}
public class VerificationResponse
{
public bool valid { get; set; }
public string message { get; set; }
public string expires_at { get; set; }
public bool requires_update { get; set; }
public string update_url { get; set; }
}
public class UpdateInfo
{
public string latest_version { get; set; }
public string current_version { get; set; }
public bool update_available { get; set; }
public bool is_mandatory { get; set; }
public string download_url { get; set; }
public string release_notes { get; set; }
}
public class LicenseInfo
{
public bool IsValid { get; set; }
public string LicenseKey { get; set; }
public DateTime? ExpiresAt { get; set; }
public string MachineId { get; set; }
}
// Beispiel-Anwendung
class Program
{
static async Task Main(string[] args)
{
// API-Key aus Umgebungsvariable oder Konfiguration
string apiKey = Environment.GetEnvironmentVariable("LICENSE_API_KEY") ?? "your-api-key-here";
using (var licenseManager = new LicenseManager(apiKey, "1.0.0"))
{
// Event-Handler registrieren
licenseManager.OnUpdateAvailable += url => Console.WriteLine($"Update verfügbar: {url}");
licenseManager.OnLicenseInvalid += msg => Console.WriteLine($"Lizenz ungültig: {msg}");
// Lizenz prüfen/aktivieren
var cache = await licenseManager.LoadLicenseCacheAsync();
if (cache != null)
{
Console.WriteLine("Gecachte Lizenz gefunden, verifiziere...");
var (valid, message) = await licenseManager.VerifyLicenseAsync();
if (!valid)
{
Console.WriteLine($"Lizenz ungültig: {message}");
await ActivateNewLicense(licenseManager);
}
else
{
Console.WriteLine($"✓ Lizenz gültig: {message}");
}
}
else
{
await ActivateNewLicense(licenseManager);
}
// Update-Check
var updateInfo = await licenseManager.CheckForUpdatesAsync();
if (updateInfo?.update_available == true)
{
Console.WriteLine($"Update verfügbar: {updateInfo.latest_version}");
if (updateInfo.is_mandatory)
Console.WriteLine("⚠️ Dies ist ein Pflicht-Update!");
}
// Lizenz-Info anzeigen
var info = licenseManager.GetLicenseInfo();
Console.WriteLine($"\nLizenz-Status:");
Console.WriteLine($"- Gültig: {info.IsValid}");
Console.WriteLine($"- Ablauf: {info.ExpiresAt}");
Console.WriteLine($"- Maschine: {info.MachineId}");
// App läuft...
Console.WriteLine("\n✓ Anwendung gestartet");
Console.WriteLine("Drücken Sie eine Taste zum Beenden...");
Console.ReadKey();
}
}
static async Task ActivateNewLicense(LicenseManager licenseManager)
{
Console.Write("Bitte Lizenzschlüssel eingeben: ");
string licenseKey = Console.ReadLine();
var (success, message) = await licenseManager.ActivateLicenseAsync(licenseKey);
if (success)
{
Console.WriteLine($"✓ {message}");
}
else
{
Console.WriteLine($"✗ {message}");
Environment.Exit(1);
}
}
}
}