using System; using System.Collections.Concurrent; using System.Collections.Generic; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.DependencyInjection; using SimApi.Communications; using StackExchange.Redis; namespace SimApi.Helpers; /// /// 认证助手(支持 Redis 和 InMemory 两种模式) /// public class SimApiAuth { private const string TokenCacheKey = "SimApi:Auth:Token:{token}"; private const string TokenSetCacheKey = "SimApi:Auth:User:{userId}"; private readonly IDistributedCache _cache; private readonly IDatabase? _redisDb; // InMemory 模式:用户 → Token集合 private readonly ConcurrentDictionary> _userTokens = new(); public SimApiAuth(IDistributedCache cache, IServiceProvider sp) { _cache = cache; _redisDb = sp.GetService()?.GetDatabase(); } /// /// 登录信息 /// /// /// /// /// public string Login(SimApiLoginItem loginItem, TimeSpan? expireTime = null, string? token = null) { expireTime ??= TimeSpan.FromDays(7); token ??= Guid.NewGuid().ToString(); var cacheKey = TokenCacheKey.Replace("{token}", token); var setCacheKey = TokenSetCacheKey.Replace("{userId}", loginItem.Id); _cache.SetString(cacheKey, SimApiUtil.Json(loginItem), new DistributedCacheEntryOptions { SlidingExpiration = expireTime }); if (_redisDb != null) { _redisDb.SetAdd(setCacheKey, token); _redisDb.KeyExpire(setCacheKey, expireTime.Value); } else { var tokens = _userTokens.GetOrAdd(loginItem.Id, _ => new ConcurrentDictionary()); tokens.TryAdd(token, 0); } return token; } /// /// 更新登陆信息 /// /// /// /// public string Update(SimApiLoginItem loginItem, string token) { var cacheKey = TokenCacheKey.Replace("{token}", token); _cache.SetString(cacheKey, SimApiUtil.Json(loginItem)); if (_redisDb != null) { var ttl = _redisDb.KeyTimeToLive(cacheKey); var setCacheKey = TokenSetCacheKey.Replace("{userId}", loginItem.Id); _redisDb.KeyExpire(setCacheKey, ttl); } return token; } /// /// 获取登陆信息 /// /// /// public SimApiLoginItem? GetLogin(string token) { var cacheKey = TokenCacheKey.Replace("{token}", token); var login = _cache.GetString(cacheKey); var resp = login != null ? SimApiUtil.FromJson(login) : null; if (resp != null && _redisDb != null) { var ttl = _redisDb.KeyTimeToLive(cacheKey); var setCacheKey = TokenSetCacheKey.Replace("{userId}", resp.Id); _redisDb.KeyExpire(setCacheKey, ttl); } return resp; } /// /// 获取所有的登录token /// /// /// public SimApiLoginItem[] GetAllLogins(string userId) { if (_redisDb != null) { var setCacheKey = TokenSetCacheKey.Replace("{userId}", userId); var allLogins = _redisDb.SetMembers(setCacheKey).ToStringArray(); var resp = new List(); foreach (var login in allLogins) { if (login != null) { var item = GetLogin(login); if (item != null) resp.Add(item); else _redisDb.SetRemove(setCacheKey, login); } } return resp.ToArray(); } else { if (!_userTokens.TryGetValue(userId, out var tokens)) return []; var resp = new List(); foreach (var token in tokens.Keys) { var item = GetLogin(token); if (item != null) resp.Add(item); else tokens.TryRemove(token, out _); } return resp.ToArray(); } } /// /// 退出所有登录 /// /// public void LogoutAll(string userId) { if (_redisDb != null) { var setCacheKey = TokenSetCacheKey.Replace("{userId}", userId); var allLogins = _redisDb.SetMembers(setCacheKey).ToStringArray(); foreach (var login in allLogins) { if (login != null) { var cacheKey = TokenCacheKey.Replace("{token}", login); _cache.Remove(cacheKey); } } _redisDb.KeyDelete(setCacheKey); } else { if (_userTokens.TryRemove(userId, out var tokens)) { foreach (var token in tokens.Keys) { var cacheKey = TokenCacheKey.Replace("{token}", token); _cache.Remove(cacheKey); } } } } /// /// 退出登陆 /// /// 登陆标识 public void Logout(string token) { var item = GetLogin(token); if (_redisDb != null) { if (item != null) { var setCacheKey = TokenSetCacheKey.Replace("{userId}", item.Id); _redisDb.SetRemove(setCacheKey, token); } } else { if (item != null && _userTokens.TryGetValue(item.Id, out var tokens)) tokens.TryRemove(token, out _); } var cacheKey = TokenCacheKey.Replace("{token}", token); _cache.Remove(cacheKey); } }