using MediatR; using CellularManagement.Domain.Services; using CellularManagement.Application.Common; using System.Text; using CellularManagement.Domain.Common; using Microsoft.Extensions.Caching.Memory; namespace CellularManagement.Application.Features.Auth.Commands.GenerateCaptcha; public class GenerateCaptchaCommandHandler : IRequestHandler> { private readonly ICaptchaService _captchaService; private readonly ICacheService _cacheService; private const string RATE_LIMIT_KEY_PREFIX = "captcha_rate_limit:"; private const int MAX_REQUESTS_PER_MINUTE = 30; public GenerateCaptchaCommandHandler( ICaptchaService captchaService, ICacheService cacheService) { _captchaService = captchaService; _cacheService = cacheService; } public async Task> Handle( GenerateCaptchaCommand request, CancellationToken cancellationToken) { try { // 获取客户端IP或标识 var clientId = request.ClientId ?? "anonymous"; var rateLimitKey = $"{RATE_LIMIT_KEY_PREFIX}{clientId}"; // 检查请求频率 var requestCount = _cacheService.Get(rateLimitKey); if (requestCount >= MAX_REQUESTS_PER_MINUTE) { var remainingTime = _cacheService.Get($"{rateLimitKey}:expiry"); var seconds = remainingTime != default ? (int)(remainingTime - DateTime.UtcNow).TotalSeconds : 60; return OperationResult.CreateFailure( $"请求过于频繁,请{seconds}秒后再试"); } // 更新请求计数 var rateLimitOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(1)); _cacheService.Set(rateLimitKey, requestCount + 1, rateLimitOptions); _cacheService.Set($"{rateLimitKey}:expiry", DateTime.UtcNow.AddMinutes(1), rateLimitOptions); // 生成验证码 var (code, imageBytes) = _captchaService.GenerateCaptcha(request.Length); // 生成唯一ID var captchaId = Guid.NewGuid().ToString(); // 将验证码存入缓存,设置5分钟过期 var cacheOptions = new MemoryCacheEntryOptions() .SetAbsoluteExpiration(TimeSpan.FromMinutes(5)); _cacheService.Set($"captcha:{captchaId}", code, cacheOptions); // 将图片转换为Base64 var base64Image = Convert.ToBase64String(imageBytes); return await Task.FromResult(OperationResult.CreateSuccess(new GenerateCaptchaResponse { CaptchaId = captchaId, ImageBase64 = base64Image })); } catch (Exception ex) { return await Task.FromResult(OperationResult.CreateFailure("生成验证码失败")); } } }