using YD_Event.Application.Auth.Dtos; using YD_Event.Core.Options; using YD_Event.Core.Enum; using Microsoft.Extensions.Options; namespace YD_Event.Application.Auth; /// /// 用户授权 /// [AllowAnonymous] public class AuthService : IDynamicApiController { private readonly ISqlSugarRepository _sysUseRepository; private readonly ISqlSugarRepository _sysUserRoleRepository; private readonly ICaptcha _captcha; private readonly IIdGenerator _idGenerator; private readonly IEasyCachingProvider _easyCachingProvider; private readonly IHttpContextAccessor _httpContextAccessor; private readonly IOptionsMonitor _roleOptionsMonitor; public AuthService(ISqlSugarRepository sysUseRepository, ISqlSugarRepository sysUserRoleRepository, ICaptcha captcha, IIdGenerator idGenerator, IEasyCachingProvider easyCachingProvider, IHttpContextAccessor httpContextAccessor, IOptionsMonitor roleOptionsMonitor) { _sysUseRepository = sysUseRepository; _sysUserRoleRepository = sysUserRoleRepository; _captcha = captcha; _idGenerator = idGenerator; _easyCachingProvider = easyCachingProvider; _httpContextAccessor = httpContextAccessor; _roleOptionsMonitor = roleOptionsMonitor; } /// /// 系统用户登录 /// /// /// [DisplayName("系统用户登录")] [HttpPost] public async Task SignIn(AdminLoginInput dto) { bool validate = _captcha.Validate(dto.Id, dto.Code); if (!validate) { throw Oops.Bah("验证码错误"); } string signInErrorCacheKey = $"login.error.{dto.Account}"; CacheValue value = await _easyCachingProvider.GetAsync(signInErrorCacheKey); //5分钟内连续验证密码失败超过4次将限制用户尝试 if (value.HasValue && value.Value > 4) { throw Oops.Bah("由于您多次登录失败,系统已限制账户登录"); } SysUser user = await _sysUseRepository.GetFirstAsync(x => x.Account == dto.Account); if (user == null) { throw Oops.Bah("用户名或密码错误"); } var context = _httpContextAccessor.HttpContext; if (user.Status == AvailabilityStatus.Disable || (user.LockExpired.HasValue && DateTime.Now < user.LockExpired)) { throw Oops.Bah("您的账号被锁定"); } if (user.Password != MD5Encryption.Encrypt($"{_idGenerator.Encode(user.Id)}{dto.Password}")) { await _easyCachingProvider.SetAsync(signInErrorCacheKey, value.Value + 1, TimeSpan.FromMinutes(5)); throw Oops.Bah("用户名或密码错误"); } long uniqueId = _idGenerator.NewLong(); string token = JWTEncryption.Encrypt(new Dictionary() { [AuthClaimsConst.AuthIdKey] = user.Id, [AuthClaimsConst.AccountKey] = user.Account, [AuthClaimsConst.UuidKey] = uniqueId, [AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.Manager }); // 获取刷新 token var refreshToken = JWTEncryption.GenerateRefreshToken(token); // 设置响应报文头 context.SigninToSwagger(token); context!.Response.Headers["access-token"] = token; context.Response.Headers["x-access-token"] = refreshToken; } /// /// 获取验证码 /// /// 验证码唯一id /// [DisplayName("获取验证码")] [HttpGet] public IActionResult Captcha([FromQuery] string id) { var data = _captcha.Generate(id); var stream = new MemoryStream(data.Bytes); return new FileStreamResult(stream, "image/gif"); } /// /// 用户注册 /// /// /// [DisplayName("用户注册")] [HttpPost] [UnitOfWork] public async Task Register(RegisterInput dto) { var codeCacheKey = $"sms:code:{dto.Phone}"; var cachedCode = await _easyCachingProvider.GetAsync(codeCacheKey); if (!cachedCode.HasValue || cachedCode.Value != dto.Code) { throw Oops.Bah("验证码错误或已过期"); } var existPhone = await _sysUseRepository.IsAnyAsync(x => x.Mobile == dto.Phone); if (existPhone) { throw Oops.Bah("该手机号已被注册"); } var user = new SysUser { Id = _idGenerator.NewLong(), Account = dto.Phone, Name = dto.Phone, Mobile = dto.Phone, Gender = Gender.Unknown, OrgId = 0, Status = AvailabilityStatus.Enable, DeleteMark = false, CreatedTime = DateTime.Now, CreatedUserId = 0 }; user.Password = MD5Encryption.Encrypt($"{_idGenerator.Encode(user.Id)}{dto.Password}"); await _sysUseRepository.InsertAsync(user); // 为新用户分配单位用户角色 var userRole = new SysUserRole { Id = _idGenerator.NewLong(), UserId = user.Id, RoleId = _roleOptionsMonitor.CurrentValue.UnitUserRoleId, CreatedTime = DateTime.Now, CreatedUserId = 0, DeleteMark = false }; await _sysUserRoleRepository.InsertAsync(userRole); await _easyCachingProvider.RemoveAsync(codeCacheKey); } /// /// 短信验证码登录 /// /// /// [DisplayName("短信验证码登录")] [HttpPost] public async Task SmsSignIn(SmsLoginInput dto) { var codeCacheKey = $"sms:code:{dto.Phone}"; var cachedCode = await _easyCachingProvider.GetAsync(codeCacheKey); if (!cachedCode.HasValue || cachedCode.Value != dto.Code) { throw Oops.Bah("验证码错误或已过期"); } SysUser user = await _sysUseRepository.GetFirstAsync(x => x.Mobile == dto.Phone); if (user == null) { throw Oops.Bah("该手机号尚未注册"); } var context = _httpContextAccessor.HttpContext; if (user.Status == AvailabilityStatus.Disable || (user.LockExpired.HasValue && DateTime.Now < user.LockExpired)) { throw Oops.Bah("您的账号被锁定"); } long uniqueId = _idGenerator.NewLong(); string token = JWTEncryption.Encrypt(new Dictionary() { [AuthClaimsConst.AuthIdKey] = user.Id, [AuthClaimsConst.AccountKey] = user.Account, [AuthClaimsConst.UuidKey] = uniqueId, [AuthClaimsConst.AuthPlatformTypeKey] = AuthPlatformType.Manager }); var refreshToken = JWTEncryption.GenerateRefreshToken(token); context.SigninToSwagger(token); context!.Response.Headers["access-token"] = token; context.Response.Headers["x-access-token"] = refreshToken; await _easyCachingProvider.RemoveAsync(codeCacheKey); } /// /// 重置密码 /// /// /// [DisplayName("重置密码")] [HttpPost] public async Task ResetPassword(ResetPasswordInput dto) { var codeCacheKey = $"sms:code:{dto.Phone}"; var cachedCode = await _easyCachingProvider.GetAsync(codeCacheKey); if (!cachedCode.HasValue || cachedCode.Value != dto.Code) { throw Oops.Bah("验证码错误或已过期"); } SysUser user = await _sysUseRepository.GetFirstAsync(x => x.Mobile == dto.Phone); if (user == null) { throw Oops.Bah("该手机号尚未注册"); } if (user.Status == AvailabilityStatus.Disable || (user.LockExpired.HasValue && DateTime.Now < user.LockExpired)) { throw Oops.Bah("您的账号被锁定"); } user.Password = MD5Encryption.Encrypt($"{_idGenerator.Encode(user.Id)}{dto.NewPassword}"); user.UpdatedTime = DateTime.Now; await _sysUseRepository.UpdateAsync(user); await _easyCachingProvider.RemoveAsync(codeCacheKey); } }