Files
TakeoutSaaS.AdminApi/src/Infrastructure/TakeoutSaaS.Infrastructure/Identity/Services/RedisAdminPasswordResetTokenStore.cs
2026-01-04 21:22:26 +08:00

67 lines
2.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.Options;
using System.Security.Cryptography;
using TakeoutSaaS.Application.Identity.Abstractions;
using TakeoutSaaS.Infrastructure.Identity.Options;
namespace TakeoutSaaS.Infrastructure.Identity.Services;
/// <summary>
/// Redis 管理后台重置密码链接令牌存储。
/// </summary>
public sealed class RedisAdminPasswordResetTokenStore(
IDistributedCache cache,
IOptions<AdminPasswordResetOptions> options)
: IAdminPasswordResetTokenStore
{
private readonly AdminPasswordResetOptions _options = options.Value;
/// <inheritdoc />
public async Task<string> IssueAsync(long userId, DateTime expiresAt, CancellationToken cancellationToken = default)
{
// 1. 生成 URL 安全的随机令牌
var token = GenerateUrlSafeToken(48);
// 2. 写入缓存ValueuserId
await cache.SetStringAsync(BuildKey(token), userId.ToString(), new DistributedCacheEntryOptions
{
AbsoluteExpiration = expiresAt
}, cancellationToken);
// 3. 返回令牌
return token;
}
/// <inheritdoc />
public async Task<long?> ConsumeAsync(string token, CancellationToken cancellationToken = default)
{
// 1. 读取缓存
var key = BuildKey(token);
var value = await cache.GetStringAsync(key, cancellationToken);
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
// 2. 删除缓存(一次性令牌)
await cache.RemoveAsync(key, cancellationToken);
// 3. 解析用户 ID
return long.TryParse(value, out var userId) ? userId : null;
}
private string BuildKey(string token) => $"{_options.Prefix}{token}";
private static string GenerateUrlSafeToken(int bytesLength)
{
var bytes = RandomNumberGenerator.GetBytes(bytesLength);
var token = Convert.ToBase64String(bytes);
return token
.Replace('+', '-')
.Replace('/', '_')
.TrimEnd('=');
}
}