chore: 同步当前开发内容

This commit is contained in:
2025-11-23 01:25:20 +08:00
parent ddf584f212
commit 1169e1f220
58 changed files with 1886 additions and 82 deletions

View File

@@ -0,0 +1,63 @@
using System;
using System.Security.Cryptography;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using TakeoutSaaS.Application.Identity.Abstractions;
using TakeoutSaaS.Application.Identity.Models;
using TakeoutSaaS.Infrastructure.Identity.Options;
namespace TakeoutSaaS.Infrastructure.Identity.Services;
/// <summary>
/// Redis 刷新令牌存储。
/// </summary>
public sealed class RedisRefreshTokenStore : IRefreshTokenStore
{
private static readonly JsonSerializerOptions JsonOptions = new(JsonSerializerDefaults.Web);
private readonly IDistributedCache _cache;
private readonly RefreshTokenStoreOptions _options;
public RedisRefreshTokenStore(IDistributedCache cache, IOptions<RefreshTokenStoreOptions> options)
{
_cache = cache;
_options = options.Value;
}
public async Task<RefreshTokenDescriptor> IssueAsync(Guid userId, DateTime expiresAt, CancellationToken cancellationToken = default)
{
var token = Convert.ToBase64String(RandomNumberGenerator.GetBytes(48));
var descriptor = new RefreshTokenDescriptor(token, userId, expiresAt, false);
var key = BuildKey(token);
var entryOptions = new DistributedCacheEntryOptions { AbsoluteExpiration = expiresAt };
await _cache.SetStringAsync(key, JsonSerializer.Serialize(descriptor, JsonOptions), entryOptions, cancellationToken);
return descriptor;
}
public async Task<RefreshTokenDescriptor?> GetAsync(string refreshToken, CancellationToken cancellationToken = default)
{
var json = await _cache.GetStringAsync(BuildKey(refreshToken), cancellationToken);
return string.IsNullOrWhiteSpace(json)
? null
: JsonSerializer.Deserialize<RefreshTokenDescriptor>(json, JsonOptions);
}
public async Task RevokeAsync(string refreshToken, CancellationToken cancellationToken = default)
{
var descriptor = await GetAsync(refreshToken, cancellationToken);
if (descriptor == null)
{
return;
}
var updated = descriptor with { Revoked = true };
var entryOptions = new DistributedCacheEntryOptions { AbsoluteExpiration = updated.ExpiresAt };
await _cache.SetStringAsync(BuildKey(refreshToken), JsonSerializer.Serialize(updated, JsonOptions), entryOptions, cancellationToken);
}
private string BuildKey(string token) => $"{_options.Prefix}{token}";
}