using Furion.DatabaseAccessor.Extensions; using Furion.EventBus; using Microsoft.Extensions.Options; using UAParser; using YBEE.EQM.Core; namespace YBEE.EQM.Application; /// /// 认证服务 /// public class SysAuthService(IOptions options, IHttpContextAccessor httpContextAccessor, IEventPublisher eventPublisher, IRepository userRep, ISysRoleUserService roleUserService, ISysMenuService menuService, IGeneralCaptchaService captchaService) : ISysAuthService, ITransient { private readonly AuthOptions _authOptions = options.Value; /// /// 登录处理 /// /// 账户密码 /// private async Task Login(LoginInput accountLoginInput) { var checkCaptcha = captchaService.CheckCode(accountLoginInput.Captcha); if (checkCaptcha.Code != 0) { throw Oops.Oh(checkCaptcha.Message); } string pwd = ""; string newPwd = ""; try { pwd = RSAEncryption.Decrypt(accountLoginInput.Password, _authOptions.RsaPrivateKey); if (!string.IsNullOrEmpty(accountLoginInput.NewPassword)) { newPwd = RSAEncryption.Decrypt(accountLoginInput.NewPassword, _authOptions.RsaPrivateKey); if (pwd == newPwd) { throw Oops.Oh(ErrorCode.E1009); } } } catch { throw Oops.Oh("密码格式错误!"); } //// 判断用户名和密码是否正确 忽略全局过滤器 //var users = await _userRep.DetachedEntities // .Include(t => t.SysOrg) // .Where(u => (u.Account.Equals(accountLoginInput.Account) || u.Mobile.Equals(accountLoginInput.Account) || u.Email.Equals(accountLoginInput.Account)) && u.IsDeleted == false) // .ToListAsync(); var user = await userRep.Include(t => t.SysOrg) .FirstOrDefaultAsync(u => u.IsDeleted == false && (u.Account.Equals(accountLoginInput.Account) || u.Mobile.Equals(accountLoginInput.Account) || u.Email.Equals(accountLoginInput.Account) )) ?? throw Oops.Oh(ErrorCode.E1001); //if (!AESEncryption.Decrypt(user.Password, _authOptions.AesPassword).Equals(pwd)) if (!PBKDF2Encryption.Compare(pwd, user.Password)) { throw Oops.Oh(ErrorCode.E1001); } //var user = (users?.FirstOrDefault(u => AESEncryption.Decrypt(u.Password, _authOptions.AesPassword).Equals(pwd))) ?? throw Oops.Oh(ErrorCode.E1001); if (!user.IsActivated && newPwd != "") { //user.Password = AESEncryption.Encrypt(newPwd, _authOptions.AesPassword); user.Password = PBKDF2Encryption.Encrypt(newPwd); user.IsActivated = true; user.ActivateTime = DateTime.Now; await user.UpdateIncludeNowAsync(new[] { nameof(user.Password), nameof(user.IsActivated), nameof(user.ActivateTime) }); } AuthOutput ret = new() { OrgName = user.SysOrg.Name, Name = user.Name, Account = user.Account, IsActivated = user.IsActivated, AccessToken = "", }; if (!user.IsActivated) { return ret; } // 验证账号是否被冻结 if (user.Status == CommonStatus.DISABLE) { throw Oops.Oh(ErrorCode.E1003); } var isSuperAdmin = await roleUserService.IsSuperAdmin(user.Id); // 生成Token令牌 var accessToken = JWTEncryption.Encrypt(new Dictionary { {ClaimConst.CLAINM_USERID, user.Id}, {ClaimConst.CLAINM_ACCOUNT, user.Account}, {ClaimConst.CLAINM_NAME, user.Name}, {ClaimConst.CLAINM_ORGID, user.SysOrgId}, {ClaimConst.CLAINM_ORGNAME, user.SysOrg.Name}, {ClaimConst.CLAINM_SUPERADMIN, isSuperAdmin.ToString()}, }); // 设置Swagger自动登录 httpContextAccessor.HttpContext.SigninToSwagger(accessToken); // 生成刷新Token令牌 var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions().ExpiredTime); // 设置刷新Token令牌 httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; ret.AccessToken = accessToken; return ret; } /// /// 账户密码登录 /// /// /// public async Task LoginByAccount([Required] LoginInput input) { return await Login(accountLoginInput: input); } /// /// 获取当前登录用户信息 /// /// public async Task GetLoginUser() { var user = await userRep.Include(t => t.SysOrg).FirstOrDefaultAsync(u => u.Id == CurrentSysUserInfo.SysUserId) ?? throw Oops.Oh(ErrorCode.E1002); var userId = user.Id; var loginOutput = user.Adapt(); var httpContext = httpContextAccessor.HttpContext; loginOutput.LastLoginTime = user.LastLoginTime = DateTime.Now; loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRequestIPv4(); var client = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]); loginOutput.LastLoginBrowser = client.UA.Family + client.UA.Major; loginOutput.LastLoginOs = client.OS.Family + client.OS.Major; // 角色信息 loginOutput.SysRoles = await roleUserService.GetLoginUserRoleList(userId); // 权限信息 loginOutput.Permissions = await menuService.GetLoginPermissionList(userId); // 系统所有权限信息 loginOutput.AllPermissions = await menuService.GetAllPermissionList(); // 菜单信息 loginOutput.Menus = await menuService.GetLoginAntMenus(userId); // 更新用户最后登录Ip和时间 await userRep.UpdateIncludeAsync(user, new[] { nameof(SysUser.LastLoginIp), nameof(SysUser.LastLoginTime) }); // 增加登录日志 await eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog", new SysLogVis { Name = loginOutput.Name, Success = true, Message = "登录成功", Ip = loginOutput.LastLoginIp, Browser = loginOutput.LastLoginBrowser, Os = loginOutput.LastLoginOs, VisType = LoginType.LOGIN, VisTime = loginOutput.LastLoginTime, Account = loginOutput.Account })); return loginOutput; } /// /// 退出 /// /// public async Task Logout() { var ip = httpContextAccessor.HttpContext.GetRequestIPv4(); httpContextAccessor.HttpContext.SignoutToSwagger(); //_httpContextAccessor.HttpContext.Response.Headers["access-token"] = "invalid token"; // 增加退出日志 await eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog", new SysLogVis { Name = CurrentSysUserInfo.Name, Success = true, Message = "退出成功", VisType = LoginType.LOGOUT, VisTime = DateTime.Now, Account = CurrentSysUserInfo.Account, Ip = ip })); } /// /// 获取验证码 /// /// public Task GetCaptcha() { // 图片大小要与前端保持一致(坐标范围) return Task.FromResult(captchaService.CreateCaptchaImage()); } /// /// 校验验证码 /// /// /// public Task VerifyCaptcha(GeneralCaptchaInput input) { return Task.FromResult(captchaService.CheckCode(input)); } /// /// 获取临时密码 /// /// /// public List GetTempPassword(List input) { List ret = []; foreach (string pwd in input) { //var npwd = AESEncryption.Encrypt(pwd, _authOptions.AesPassword); var npwd = PBKDF2Encryption.Encrypt(pwd); ret.Add(npwd); } return ret; } }