using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using WorkCameraExport.Models;
using WorkCameraExport.Services.Interfaces;
namespace WorkCameraExport.Services
{
///
/// 配置服务实现 - 负责配置文件和登录凭证的管理
///
public class ConfigService : IConfigService
{
// 用于加密凭证的密钥(AES-256 需要 32 字节密钥,16 字节 IV)
private static readonly byte[] EncryptionKey = Encoding.UTF8.GetBytes("WorkCameraExport2025SecretKey!!!"); // 32 bytes
private static readonly byte[] EncryptionIV = Encoding.UTF8.GetBytes("WCE2025InitVect!"); // 16 bytes
private static readonly JsonSerializerOptions JsonOptions = new()
{
WriteIndented = true,
PropertyNameCaseInsensitive = true
};
public ConfigService()
{
}
///
/// 用于测试的构造函数
///
public ConfigService(string _)
{
}
#region IConfigService 实现
public string AppDataPath => PathService.BaseDirectory;
public string TempPath => PathService.TempDirectory;
public string LogPath => PathService.LogDirectory;
public bool HasSavedCredentials => File.Exists(PathService.CredentialsFile);
public AppConfig LoadConfig()
{
try
{
var path = PathService.ConfigFile;
if (File.Exists(path))
{
var json = File.ReadAllText(path);
var config = JsonSerializer.Deserialize(json, JsonOptions);
if (config != null)
{
config.Validate();
return config;
}
}
}
catch
{
// 加载失败时返回默认配置
}
return AppConfig.CreateDefault();
}
public void SaveConfig(AppConfig config)
{
config.Validate();
var json = JsonSerializer.Serialize(config, JsonOptions);
File.WriteAllText(PathService.ConfigFile, json);
}
public void SaveCredentials(string serverUrl, string token, string username)
{
var credentials = new CredentialsData
{
ServerUrl = serverUrl,
Token = token,
Username = username,
SavedAt = DateTime.Now
};
var json = JsonSerializer.Serialize(credentials, JsonOptions);
var encrypted = Encrypt(json);
File.WriteAllBytes(PathService.CredentialsFile, encrypted);
}
public (string ServerUrl, string Token, string Username)? LoadCredentials()
{
try
{
var path = PathService.CredentialsFile;
if (!File.Exists(path))
return null;
var encrypted = File.ReadAllBytes(path);
var json = Decrypt(encrypted);
var credentials = JsonSerializer.Deserialize(json, JsonOptions);
if (credentials != null &&
!string.IsNullOrEmpty(credentials.ServerUrl) &&
!string.IsNullOrEmpty(credentials.Token))
{
return (credentials.ServerUrl, credentials.Token, credentials.Username);
}
}
catch
{
// 解密失败时清除凭证
ClearCredentials();
}
return null;
}
public void ClearCredentials()
{
try
{
var path = PathService.CredentialsFile;
if (File.Exists(path))
{
File.Delete(path);
}
}
catch
{
// 忽略删除错误
}
}
public void CleanTempFiles()
{
try
{
var tempPath = PathService.TempDirectory;
if (Directory.Exists(tempPath))
{
var directory = new DirectoryInfo(tempPath);
foreach (var file in directory.GetFiles())
{
try { file.Delete(); } catch { }
}
foreach (var dir in directory.GetDirectories())
{
try { dir.Delete(true); } catch { }
}
}
}
catch
{
// 忽略清理错误
}
}
#endregion
#region 私有方法
private static byte[] Encrypt(string plainText)
{
using var aes = Aes.Create();
aes.Key = EncryptionKey;
aes.IV = EncryptionIV;
using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
using var ms = new MemoryStream();
using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
using (var sw = new StreamWriter(cs))
{
sw.Write(plainText);
}
return ms.ToArray();
}
private static string Decrypt(byte[] cipherText)
{
using var aes = Aes.Create();
aes.Key = EncryptionKey;
aes.IV = EncryptionIV;
using var decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
using var ms = new MemoryStream(cipherText);
using var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read);
using var sr = new StreamReader(cs);
return sr.ReadToEnd();
}
#endregion
#region 内部类
private class CredentialsData
{
public string ServerUrl { get; set; } = "";
public string Token { get; set; } = "";
public string Username { get; set; } = "";
public DateTime SavedAt { get; set; }
}
#endregion
}
}