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.

132 lines
3.7 KiB

using System;
using System.Threading.Tasks;
using CellularManagement.Domain.Services;
using Microsoft.Extensions.Caching.Distributed;
using System.Text.Json;
namespace CellularManagement.Infrastructure.Services;
/// <summary>
/// 邮箱验证码服务
/// 提供验证码生成、发送和验证的具体实现
/// </summary>
public class EmailVerificationService : IEmailVerificationService
{
private readonly IEmailService _emailService;
private readonly IDistributedCache _cache;
private const string CacheKeyPrefix = "EmailVerification_";
private const int VerificationCodeLength = 6;
private const int VerificationCodeExpirationMinutes = 5;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="emailService">邮箱服务</param>
/// <param name="cache">分布式缓存</param>
public EmailVerificationService(IEmailService emailService, IDistributedCache cache)
{
_emailService = emailService;
_cache = cache;
}
/// <summary>
/// 生成并发送验证码
/// </summary>
/// <param name="email">邮箱地址</param>
/// <returns>是否发送成功</returns>
public async Task<bool> GenerateAndSendVerificationCodeAsync(string email)
{
if (!_emailService.ValidateEmail(email))
{
return false;
}
// 生成6位数字验证码
var verificationCode = GenerateVerificationCode();
// 将验证码保存到缓存
var cacheKey = $"{CacheKeyPrefix}{email}";
var cacheValue = JsonSerializer.Serialize(new
{
Code = verificationCode,
CreatedAt = DateTime.UtcNow
});
await _cache.SetStringAsync(
cacheKey,
cacheValue,
new DistributedCacheEntryOptions
{
AbsoluteExpirationRelativeToNow = TimeSpan.FromMinutes(VerificationCodeExpirationMinutes)
});
// 发送验证码邮件
return await _emailService.SendVerificationCodeAsync(email, verificationCode);
}
/// <summary>
/// 验证验证码
/// </summary>
/// <param name="email">邮箱地址</param>
/// <param name="code">验证码</param>
/// <returns>验证结果</returns>
public async Task<bool> VerifyCodeAsync(string email, string code)
{
var cacheKey = $"{CacheKeyPrefix}{email}";
var cachedValue = await _cache.GetStringAsync(cacheKey);
if (string.IsNullOrEmpty(cachedValue))
{
return false;
}
var verificationData = JsonSerializer.Deserialize<VerificationData>(cachedValue);
if (verificationData == null)
{
return false;
}
// 验证码是否过期
if (DateTime.UtcNow - verificationData.CreatedAt > TimeSpan.FromMinutes(VerificationCodeExpirationMinutes))
{
await _cache.RemoveAsync(cacheKey);
return false;
}
// 验证码是否匹配
if (verificationData.Code != code)
{
return false;
}
// 验证成功后删除缓存
await _cache.RemoveAsync(cacheKey);
return true;
}
/// <summary>
/// 生成验证码
/// </summary>
private string GenerateVerificationCode()
{
var random = new Random();
var code = string.Empty;
for (int i = 0; i < VerificationCodeLength; i++)
{
code += random.Next(0, 10).ToString();
}
return code;
}
/// <summary>
/// 验证数据
/// </summary>
private class VerificationData
{
public string Code { get; set; } = string.Empty;
public DateTime CreatedAt { get; set; }
}
}