Files
RhythmicWallpaper/AudioVisualizer/SSO/TokenManager.cs

161 lines
5.6 KiB
C#

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<LoginMeta>(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);
}
}
}