You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
79 lines
3.1 KiB
79 lines
3.1 KiB
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<GenerateCaptchaCommand, OperationResult<GenerateCaptchaResponse>>
|
|
{
|
|
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<OperationResult<GenerateCaptchaResponse>> Handle(
|
|
GenerateCaptchaCommand request,
|
|
CancellationToken cancellationToken)
|
|
{
|
|
try
|
|
{
|
|
// 获取客户端IP或标识
|
|
var clientId = request.ClientId ?? "anonymous";
|
|
var rateLimitKey = $"{RATE_LIMIT_KEY_PREFIX}{clientId}";
|
|
|
|
// 检查请求频率
|
|
var requestCount = _cacheService.Get<int>(rateLimitKey);
|
|
if (requestCount >= MAX_REQUESTS_PER_MINUTE)
|
|
{
|
|
var remainingTime = _cacheService.Get<DateTime>($"{rateLimitKey}:expiry");
|
|
var seconds = remainingTime != default
|
|
? (int)(remainingTime - DateTime.UtcNow).TotalSeconds
|
|
: 60;
|
|
|
|
return OperationResult<GenerateCaptchaResponse>.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<GenerateCaptchaResponse>.CreateSuccess(new GenerateCaptchaResponse
|
|
{
|
|
CaptchaId = captchaId,
|
|
ImageBase64 = base64Image
|
|
}));
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return await Task.FromResult(OperationResult<GenerateCaptchaResponse>.CreateFailure("生成验证码失败"));
|
|
}
|
|
}
|
|
}
|