|
1 | 1 | using IdentityModel.Client; |
2 | 2 | using Microsoft.Extensions.Caching.Distributed; |
| 3 | +using Microsoft.Extensions.Caching.Hybrid; |
3 | 4 | using Microsoft.Extensions.Options; |
4 | 5 | using System.IdentityModel.Tokens.Jwt; |
5 | 6 | using System.Text.Json; |
6 | 7 | using System.Text.Json.Serialization; |
| 8 | +using Ubik.Accounting.WebApp.Shared.Security; |
7 | 9 | using Ubik.ApiService.Common.Configure.Options; |
8 | 10 | using Ubik.Security.Contracts.Users.Results; |
9 | 11 |
|
10 | 12 | namespace Ubik.Accounting.WebApp.Security |
11 | 13 | { |
12 | | - public class TokenCacheService(IDistributedCache cache, IOptions<AuthServerOptions> authOptions, IHttpClientFactory factory) |
| 14 | + public class TokenCacheService(HybridCache cache, IOptions<AuthServerOptions> authOptions, IHttpClientFactory factory) |
13 | 15 | { |
14 | | - private readonly IDistributedCache _cache = cache; |
15 | 16 | private readonly AuthServerOptions _authOptions = authOptions.Value; |
16 | 17 | private readonly HttpClient _httpClient = factory.CreateClient("TokenClient"); |
17 | 18 |
|
18 | | - private static readonly JsonSerializerOptions _serializerOptions = new() |
19 | | - { |
20 | | - PropertyNamingPolicy = null, |
21 | | - WriteIndented = true, |
22 | | - AllowTrailingCommas = true, |
23 | | - DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull |
24 | | - }; |
25 | | - |
26 | 19 | public async Task RemoveUserTokenAsync(string key) |
27 | 20 | { |
28 | | - await _cache.RemoveAsync($"webapp_{key}"); |
| 21 | + await cache.RemoveAsync($"webapp_{key}"); |
29 | 22 | } |
30 | 23 |
|
31 | 24 | public async Task SetUserTokenAsync(TokenCacheEntry token) |
32 | 25 | { |
33 | | - var toCache = JsonSerializer.SerializeToUtf8Bytes(token, options: _serializerOptions); |
34 | | - |
35 | | - await _cache.SetAsync($"webapp_{token.UserId}", toCache, |
36 | | - new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(120) }); |
| 26 | + await cache.SetAsync($"webapp_{token.UserId}", token, new HybridCacheEntryOptions() |
| 27 | + { |
| 28 | + Expiration = TimeSpan.FromMinutes(120), |
| 29 | + LocalCacheExpiration = TimeSpan.FromSeconds(10) |
| 30 | + }); |
37 | 31 | } |
38 | 32 |
|
39 | 33 | public async Task<TokenCacheEntry?> GetUserTokenAsync(string? userId) |
40 | 34 | { |
41 | 35 | if (userId == null) return null; |
42 | 36 |
|
43 | | - var token = await _cache.GetAsync($"webapp_{userId}"); |
| 37 | + var token = await cache.GetOrCreateAsync<TokenCacheEntry?>($"webapp_{userId}", factory: null!, |
| 38 | + new HybridCacheEntryOptions() { Flags = HybridCacheEntryFlags.DisableUnderlyingData }); |
44 | 39 |
|
45 | 40 | if (token == null) return null; |
46 | 41 |
|
47 | | - var cachedResult = JsonSerializer.Deserialize<TokenCacheEntry>(token, _serializerOptions); |
48 | | - |
49 | | - if (cachedResult == null) return null; |
| 42 | + token = await RefreshTokenAsync(token, userId); |
50 | 43 |
|
51 | | - cachedResult = await RefreshTokenAsync(cachedResult, userId); |
52 | | - |
53 | | - return cachedResult; |
| 44 | + return token; |
54 | 45 | } |
55 | 46 |
|
56 | 47 | private async Task<TokenCacheEntry?> RefreshTokenAsync(TokenCacheEntry actualToken, string userId) |
@@ -109,22 +100,22 @@ private Dictionary<string, string> ValuesForRefresh(string token) |
109 | 100 | } |
110 | 101 | public async Task SetUserInfoAsync(UserAdminOrMeResult userInfo) |
111 | 102 | { |
112 | | - var toCache = JsonSerializer.SerializeToUtf8Bytes(userInfo, options: _serializerOptions); |
| 103 | + await cache.SetAsync($"webapp_{userInfo.Email}_auth", userInfo, new HybridCacheEntryOptions() |
| 104 | + { |
| 105 | + Expiration = TimeSpan.FromMinutes(_authOptions.CookieRefreshTimeInMinutes + 120), |
| 106 | + LocalCacheExpiration = TimeSpan.FromSeconds(15) |
| 107 | + }); |
113 | 108 |
|
114 | | - await _cache.SetAsync($"webapp_{userInfo.Email}_auth", toCache, new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(_authOptions.CookieRefreshTimeInMinutes + 120) }); |
115 | 109 | } |
116 | 110 |
|
117 | 111 | public async Task<UserAdminOrMeResult?> GetUserInfoAsync(string? userEmail) |
118 | 112 | { |
119 | 113 | if (userEmail == null) return null; |
120 | 114 |
|
121 | | - var user = await _cache.GetAsync($"webapp_{userEmail}_auth"); |
122 | | - |
123 | | - if (user == null) return null; |
124 | | - |
125 | | - var cachedResult = JsonSerializer.Deserialize<UserAdminOrMeResult>(user, _serializerOptions); |
| 115 | + var user = await cache.GetOrCreateAsync<UserAdminOrMeResult?>($"webapp_{userEmail}_auth", factory: null!, |
| 116 | + new HybridCacheEntryOptions() { Flags = HybridCacheEntryFlags.DisableUnderlyingData }); |
126 | 117 |
|
127 | | - return cachedResult; |
| 118 | + return user ?? null; |
128 | 119 | } |
129 | 120 | } |
130 | 121 |
|
|
0 commit comments