using System.Security.Cryptography; using System.Text; using System.Text.Json; namespace AudioWallpaper.SSO { public interface ITokenStore { void Save(string tokenName, string token); string? Get(string tokenName); void Clear(string tokenName); } public class EncryptedFileTokenStore : ITokenStore { private readonly string _storagePath; private readonly object _lock = new(); public EncryptedFileTokenStore(string storageDirectory) { _storagePath = storageDirectory; Directory.CreateDirectory(_storagePath); } private string GetTokenFilePath(string tokenName) => Path.Combine(_storagePath, $"{tokenName}.token"); public void Save(string tokenName, string token) { var data = Encoding.UTF8.GetBytes(token); var encrypted = ProtectedData.Protect(data, null, DataProtectionScope.CurrentUser); lock (_lock) { File.WriteAllBytes(GetTokenFilePath(tokenName), encrypted); } } public string? Get(string tokenName) { var path = GetTokenFilePath(tokenName); if (!File.Exists(path)) return null; try { lock (_lock) { var encrypted = File.ReadAllBytes(path); var decrypted = ProtectedData.Unprotect(encrypted, null, DataProtectionScope.CurrentUser); return Encoding.UTF8.GetString(decrypted); } } catch { return null; // 可选:记录日志 } } public void Clear(string tokenName) { var path = GetTokenFilePath(tokenName); lock (_lock) { if (File.Exists(path)) File.Delete(path); } } } public class TokenManager { private readonly ITokenStore _store; private const string AccessTokenKey = "access_token"; private const string RefreshTokenKey = "refresh_token"; private const string IdTokenKey = "id_token"; private const string LoginMetaKey = "login_state"; public TokenManager(ITokenStore store) { _store = store ?? throw new ArgumentNullException(nameof(store)); } // 保存 TokenSet public void SaveToken(TokenSet tokens) { SaveToken(tokens, null); } public void SaveToken(TokenSet tokens, UserInfoSet? userInfoSet) { if (tokens == null) throw new ArgumentNullException(nameof(tokens)); if (string.IsNullOrWhiteSpace(tokens.AccessToken)) throw new ArgumentException("Access token is required."); if (string.IsNullOrWhiteSpace(tokens.RefreshToken)) throw new ArgumentException("Refresh token is required."); if (string.IsNullOrWhiteSpace(tokens.IdToken)) throw new ArgumentException("ID token is required."); _store.Save(AccessTokenKey, tokens.AccessToken); _store.Save(RefreshTokenKey, tokens.RefreshToken); _store.Save(IdTokenKey, tokens.IdToken); if (userInfoSet != null) { LoginMeta loginMeta = new LoginMeta { IsLoggedIn = true, UserInfo = userInfoSet }; SaveLoginMeta(loginMeta); } } public void SaveLoginMeta(LoginMeta? loginMeta) { if (loginMeta == null) throw new ArgumentNullException(nameof(loginMeta)); string loginMetaJson = JsonSerializer.Serialize(loginMeta); _store.Save(LoginMetaKey, loginMetaJson); } // 保存单个 token public void SaveToken(string name, string token) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Token name is required."); if (string.IsNullOrWhiteSpace(token)) throw new ArgumentException("Token value is required."); _store.Save(name, token); } // 获取 TokenSet public TokenSet? GetToken() { var accessToken = _store.Get(AccessTokenKey); var refreshToken = _store.Get(RefreshTokenKey); var idToken = _store.Get(IdTokenKey); if (string.IsNullOrWhiteSpace(accessToken) && string.IsNullOrWhiteSpace(refreshToken) && string.IsNullOrWhiteSpace(idToken)) return null; return new TokenSet(accessToken ?? string.Empty, refreshToken ?? string.Empty, idToken ?? string.Empty); } // 获取指定 token public string? GetToken(string name) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Token name is required."); return _store.Get(name); } // 获取登录状态 public LoginMeta? GetLoginMeta() { var loginMetaJson = _store.Get(LoginMetaKey); if (string.IsNullOrWhiteSpace(loginMetaJson)) return null; try { return JsonSerializer.Deserialize(loginMetaJson); } catch (JsonException) { return null; // 可选:记录日志 } } // 清除全部 token public void ClearToken() { _store.Clear(AccessTokenKey); _store.Clear(RefreshTokenKey); _store.Clear(IdTokenKey); _store.Clear(LoginMetaKey); } // 清除指定 token public void ClearToken(string name) { if (string.IsNullOrWhiteSpace(name)) throw new ArgumentException("Token name is required."); _store.Clear(name); } } }