feat: 新增找回密码功能接口

This commit is contained in:
橙子
2024-10-03 01:10:32 +08:00
parent 94ee0fb058
commit d7629763ef
13 changed files with 362 additions and 222 deletions

View File

@@ -0,0 +1,24 @@
namespace Yi.Framework.Rbac.Application.Contracts.Dtos.Account;
public class RetrievePasswordDto
{
/// <summary>
/// 密码
/// </summary>
public string Password { get; set; }
/// <summary>
/// 唯一标识码
/// </summary>
public string? Uuid { get; set; }
/// <summary>
/// 电话
/// </summary>
public long Phone { get; set; }
/// <summary>
/// 验证码
/// </summary>
public string? Code { get; set; }
}

View File

@@ -27,6 +27,7 @@ using Yi.Framework.Rbac.Domain.Repositories;
using Yi.Framework.Rbac.Domain.Shared.Caches;
using Yi.Framework.Rbac.Domain.Shared.Consts;
using Yi.Framework.Rbac.Domain.Shared.Dtos;
using Yi.Framework.Rbac.Domain.Shared.Enums;
using Yi.Framework.Rbac.Domain.Shared.Etos;
using Yi.Framework.Rbac.Domain.Shared.Options;
using Yi.Framework.SqlSugarCore.Abstractions;
@@ -44,6 +45,7 @@ namespace Yi.Framework.Rbac.Application.Services
private IDistributedCache<UserInfoCacheItem, UserInfoCacheKey> _userCache;
private UserManager _userManager;
private IHttpContextAccessor _httpContextAccessor;
public AccountService(IUserRepository userRepository,
ICurrentUser currentUser,
IAccountManager accountManager,
@@ -127,7 +129,7 @@ namespace Yi.Framework.Rbac.Application.Services
loginEto.UserId = userInfo.User.Id;
await LocalEventBus.PublishAsync(loginEto);
}
return new { Token = accessToken, RefreshToken = refreshToken };
}
@@ -178,14 +180,35 @@ namespace Yi.Framework.Rbac.Application.Services
/// <summary>
/// 注册 手机验证码
/// 手机验证码-注册
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("captcha-phone")]
[AllowAnonymous]
public async Task<object> PostCaptchaPhoneForRegisterAsync(PhoneCaptchaImageDto input)
{
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.Register, input);
}
/// <summary>
/// 手机验证码-找回密码
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
[HttpPost("captcha-phone/repassword")]
public async Task<object> PostCaptchaPhoneForRetrievePasswordAsync(PhoneCaptchaImageDto input)
{
return await PostCaptchaPhoneAsync(ValidationPhoneTypeEnum.RetrievePassword, input);
}
/// <summary>
/// 手机验证码
/// </summary>
/// <returns></returns>
[AllowAnonymous]
public async Task<object> PostCaptchaPhone(PhoneCaptchaImageDto input)
private async Task<object> PostCaptchaPhoneAsync(ValidationPhoneTypeEnum validationPhoneType,
PhoneCaptchaImageDto input)
{
await ValidationPhone(input.Phone);
var value = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(input.Phone));
var value = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(validationPhoneType, input.Phone));
//防止暴刷
if (value is not null)
@@ -200,7 +223,8 @@ namespace Yi.Framework.Rbac.Application.Services
var uuid = Guid.NewGuid();
await _aliyunManger.SendSmsAsync(input.Phone, code);
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(input.Phone), new CaptchaPhoneCacheItem(code),
await _phoneCache.SetAsync(new CaptchaPhoneCacheKey(ValidationPhoneTypeEnum.Register, input.Phone),
new CaptchaPhoneCacheItem(code),
new DistributedCacheEntryOptions { SlidingExpiration = TimeSpan.FromMinutes(10) });
return new
{
@@ -211,19 +235,44 @@ namespace Yi.Framework.Rbac.Application.Services
/// <summary>
/// 校验电话验证码,需要与电话号码绑定
/// </summary>
private async Task ValidationPhoneCaptchaAsync(RegisterDto input)
private async Task ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum validationPhoneType, long phone,
string code)
{
var item = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
if (item is not null && item.Code.Equals($"{input.Code}"))
var item = await _phoneCache.GetAsync(new CaptchaPhoneCacheKey(validationPhoneType, phone.ToString()));
if (item is not null && item.Code.Equals($"{code}"))
{
//成功,需要清空
await _phoneCache.RemoveAsync(new CaptchaPhoneCacheKey(input.Phone.ToString()));
await _phoneCache.RemoveAsync(new CaptchaPhoneCacheKey(validationPhoneType, code.ToString()));
return;
}
throw new UserFriendlyException("验证码错误");
}
/// <summary>
/// 找回密码
/// </summary>
/// <param name="input"></param>
[AllowAnonymous]
[UnitOfWork]
public async Task PostRetrievePasswordAsync(RetrievePasswordDto input)
{
if (_rbacOptions.EnableCaptcha)
{
//校验验证码,根据电话号码获取 value比对验证码已经uuid
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.RetrievePassword, input.Phone, input.Code);
}
var entity = await _userRepository.GetFirstAsync(x => x.Phone == input.Phone);
if (entity is null)
{
throw new UserFriendlyException("该手机号码未注册");
}
await _accountManager.RestPasswordAsync(entity.Id, input.Password);
}
/// <summary>
/// 注册,需要验证码通过
/// </summary>
@@ -241,16 +290,16 @@ namespace Yi.Framework.Rbac.Application.Services
if (_rbacOptions.EnableCaptcha)
{
//校验验证码,根据电话号码获取 value比对验证码已经uuid
await ValidationPhoneCaptchaAsync(input);
await ValidationPhoneCaptchaAsync(ValidationPhoneTypeEnum.Register, input.Phone, input.Code);
}
//注册领域逻辑
await _accountManager.RegisterAsync(input.UserName, input.Password, input.Phone,input.Nick);
await _accountManager.RegisterAsync(input.UserName, input.Password, input.Phone, input.Nick);
}
/// <summary>
/// 查询已登录的账户信息,已缓存
/// 查询已登录的账户信息
/// </summary>
/// <returns></returns>
[Route("account")]
@@ -270,9 +319,6 @@ namespace Yi.Framework.Rbac.Application.Services
}
/// <summary>
/// 获取当前登录用户的前端路由
/// 支持ruoyi/pure
@@ -280,7 +326,7 @@ namespace Yi.Framework.Rbac.Application.Services
/// <returns></returns>
[Authorize]
[Route("account/Vue3Router/{routerType?}")]
public async Task<object> GetVue3Router([FromRoute]string? routerType)
public async Task<object> GetVue3Router([FromRoute] string? routerType)
{
var userId = _currentUser.Id;
if (_currentUser.Id is null)
@@ -298,18 +344,19 @@ namespace Yi.Framework.Rbac.Application.Services
}
object output = null;
if (routerType is null ||routerType=="ruoyi")
if (routerType is null || routerType == "ruoyi")
{
//将后端菜单转换成前端路由,组件级别需要过滤
output =
ObjectMapper.Map<List<MenuDto>, List<MenuAggregateRoot>>(menus).Vue3RuoYiRouterBuild();
}
else if (routerType =="pure")
else if (routerType == "pure")
{
//将后端菜单转换成前端路由,组件级别需要过滤
output =
ObjectMapper.Map<List<MenuDto>, List<MenuAggregateRoot>>(menus).Vue3PureRouterBuild();
}
return output;
}

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Yi.Framework.Rbac.Domain.Shared.Enums;
namespace Yi.Framework.Rbac.Domain.Shared.Caches
{
@@ -14,13 +15,15 @@ namespace Yi.Framework.Rbac.Domain.Shared.Caches
public class CaptchaPhoneCacheKey
{
public CaptchaPhoneCacheKey(string phone) { Phone = phone; }
public CaptchaPhoneCacheKey(ValidationPhoneTypeEnum validationPhoneType,string phone) { Phone = phone;
ValidationPhoneType = validationPhoneType;
}
public ValidationPhoneTypeEnum ValidationPhoneType { get; set; }
public string Phone { get; set; }
public override string ToString()
{
return $"Phone:{Phone}";
return $"Phone:{ValidationPhoneType.ToString()}:{Phone}";
}
}
}

View File

@@ -0,0 +1,13 @@
namespace Yi.Framework.Rbac.Domain.Shared.Enums;
public enum ValidationPhoneTypeEnum
{
/// <summary>
/// 注册
/// </summary>
Register,
/// <summary>
/// 忘记密码
/// </summary>
RetrievePassword
}

View File

@@ -180,6 +180,8 @@ namespace Yi.Framework.Rbac.Domain.Managers
}
return false;
}
/// <summary>
/// 令牌转换
@@ -250,7 +252,7 @@ namespace Yi.Framework.Rbac.Domain.Managers
}
/// <summary>
/// 重置密码
/// 重置密码,也可以是找回密码
/// </summary>
/// <param name="userId"></param>
/// <param name="password"></param>
@@ -258,7 +260,6 @@ namespace Yi.Framework.Rbac.Domain.Managers
public async Task<bool> RestPasswordAsync(Guid userId, string password)
{
var user = await _repository.GetByIdAsync(userId);
// EntityHelper.TrySetId(user, () => GuidGenerator.Create(), true);
user.EncryPassword.Password = password;
user.BuildPassword();
return await _repository.UpdateAsync(user);
@@ -276,7 +277,6 @@ namespace Yi.Framework.Rbac.Domain.Managers
var user = new UserAggregateRoot(userName, password, phone,nick);
await _userManager.CreateAsync(user);
await _userManager.SetDefautRoleAsync(user.Id);
}
}

View File

@@ -51,12 +51,12 @@ namespace Yi.Framework.Rbac.Domain.Operlog
/// <summary>
/// 请求参数
///</summary>
[SugarColumn(ColumnName = "RequestParam")]
[SugarColumn(ColumnName = "RequestParam",ColumnDataType = StaticConfig.CodeFirst_BigString)]
public string? RequestParam { get; set; }
/// <summary>
/// 请求结果
///</summary>
[SugarColumn(ColumnName = "RequestResult", Length = 9999)]
[SugarColumn(ColumnName = "RequestResult",ColumnDataType = StaticConfig.CodeFirst_BigString)]
public string? RequestResult { get; set; }
public DateTime CreationTime { get; set; }