From 1c73e36cb64345cae617056f2b42a1379de1c9c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=86=99=E6=84=8F?= Date: Thu, 29 May 2025 13:58:38 +0800 Subject: [PATCH] =?UTF-8?q?style:=20=E8=B0=83=E6=95=B4=20SysAuthService=20?= =?UTF-8?q?=E6=8D=A2=E8=A1=8C=E7=AC=A6=E4=B8=BA=20CRLF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/Auth/SysAuthService.cs | 774 +++++++++--------- 1 file changed, 387 insertions(+), 387 deletions(-) diff --git a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs index 731bf0f2..fcaa8886 100644 --- a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs @@ -1,348 +1,348 @@ -// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 -// -// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 -// -// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! - -using Furion.SpecificationDocument; -using Lazy.Captcha.Core; - -namespace Admin.NET.Core.Service; - -/// -/// 系统登录授权服务 🧩 -/// -[ApiDescriptionSettings(Order = 500, Description = "登录授权")] -[AppApiDescription("登录授权")] -public class SysAuthService : IDynamicApiController, ITransient -{ - private readonly UserManager _userManager; - private readonly SqlSugarRepository _sysUserRep; - private readonly SysConfigService _sysConfigService; - private readonly SysCacheService _sysCacheService; - private readonly IHttpContextAccessor _httpContextAccessor; - private readonly ICaptcha _captcha; - private readonly IEventPublisher _eventPublisher; - - public SysAuthService(UserManager userManager, - SqlSugarRepository sysUserRep, - SysConfigService sysConfigService, - SysCacheService sysCacheService, - IHttpContextAccessor httpContextAccessor, - ICaptcha captcha, - IEventPublisher eventPublisher) - { - _userManager = userManager; - _sysUserRep = sysUserRep; - _sysConfigService = sysConfigService; - _sysCacheService = sysCacheService; - _httpContextAccessor = httpContextAccessor; - _captcha = captcha; - _eventPublisher = eventPublisher; - } - - /// - /// 账号密码登录 🔖 - /// - /// - /// - [DisplayName("账号密码登录")] +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +using Furion.SpecificationDocument; +using Lazy.Captcha.Core; + +namespace Admin.NET.Core.Service; + +/// +/// 系统登录授权服务 🧩 +/// +[ApiDescriptionSettings(Order = 500, Description = "登录授权")] +[AppApiDescription("登录授权")] +public class SysAuthService : IDynamicApiController, ITransient +{ + private readonly UserManager _userManager; + private readonly SqlSugarRepository _sysUserRep; + private readonly SysConfigService _sysConfigService; + private readonly SysCacheService _sysCacheService; + private readonly IHttpContextAccessor _httpContextAccessor; + private readonly ICaptcha _captcha; + private readonly IEventPublisher _eventPublisher; + + public SysAuthService(UserManager userManager, + SqlSugarRepository sysUserRep, + SysConfigService sysConfigService, + SysCacheService sysCacheService, + IHttpContextAccessor httpContextAccessor, + ICaptcha captcha, + IEventPublisher eventPublisher) + { + _userManager = userManager; + _sysUserRep = sysUserRep; + _sysConfigService = sysConfigService; + _sysCacheService = sysCacheService; + _httpContextAccessor = httpContextAccessor; + _captcha = captcha; + _eventPublisher = eventPublisher; + } + + /// + /// 账号密码登录 🔖 + /// + /// + /// + [DisplayName("账号密码登录")] [AllowAnonymous] - public virtual async Task Login([Required] LoginInput input) - { - // 判断密码错误次数(缓存30分钟) - var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}"; - var passwordErrorTimes = _sysCacheService.Get(keyPasswordErrorTimes); - var passwordMaxErrorTimes = await _sysConfigService.GetConfigValueByCode(ConfigConst.SysPasswordMaxErrorTimes); - // 若未配置或误配置为0、负数, 则默认密码错误次数最大为5次 - if (passwordMaxErrorTimes < 1) passwordMaxErrorTimes = 5; - if (passwordErrorTimes > passwordMaxErrorTimes) throw Oops.Oh(ErrorCodeEnum.D1027); - + public virtual async Task Login([Required] LoginInput input) + { + // 判断密码错误次数(缓存30分钟) + var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{input.Account}"; + var passwordErrorTimes = _sysCacheService.Get(keyPasswordErrorTimes); + var passwordMaxErrorTimes = await _sysConfigService.GetConfigValueByCode(ConfigConst.SysPasswordMaxErrorTimes); + // 若未配置或误配置为0、负数, 则默认密码错误次数最大为5次 + if (passwordMaxErrorTimes < 1) passwordMaxErrorTimes = 5; + if (passwordErrorTimes > passwordMaxErrorTimes) throw Oops.Oh(ErrorCodeEnum.D1027); + // 判断是否开启验证码并校验 - input.TenantId = input.TenantId <= 0 ? SqlSugarConst.DefaultTenantId : input.TenantId; + input.TenantId = input.TenantId <= 0 ? SqlSugarConst.DefaultTenantId : input.TenantId; var tenant = _sysCacheService.Get>(CacheConst.KeyTenant)?.FirstOrDefault(u => u.Id == input.TenantId); if (tenant == null) { await App.GetRequiredService().CacheTenant(); // 重新生成租户列表缓存 tenant = _sysCacheService.Get>(CacheConst.KeyTenant)?.FirstOrDefault(u => u.Id == input.TenantId); if (tenant == null) throw Oops.Oh(ErrorCodeEnum.D0007); - } - if (tenant.Captcha == true && !_captcha.Validate(input.CodeId.ToString(), input.Code)) - throw Oops.Oh(ErrorCodeEnum.D0008); - - // 获取并验证账号 - var user = await GetLoginUser(input.TenantId, account: input.Account); - - // 是否开启域登录验证 - if (await _sysConfigService.GetConfigValueByCode(ConfigConst.SysDomainLogin)) - { - var userLdap = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.UserId == user.Id && u.TenantId == user.TenantId); - if (userLdap == null) - { - VerifyPassword(input.Password, keyPasswordErrorTimes, passwordErrorTimes, user); - } - else if (!await App.GetRequiredService().AuthAccount(user.TenantId, userLdap.Account, CryptogramUtil.Decrypt(input.Password))) - { - _sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); - throw Oops.Oh(ErrorCodeEnum.D1000); - } - } - else - VerifyPassword(input.Password, keyPasswordErrorTimes, passwordErrorTimes, user); - - // 登录成功则清空密码错误次数 - _sysCacheService.Remove(keyPasswordErrorTimes); - - return await CreateToken(user); - } - - /// - /// 获取登录用户 - /// - /// - /// - /// - /// + } + if (tenant.Captcha == true && !_captcha.Validate(input.CodeId.ToString(), input.Code)) + throw Oops.Oh(ErrorCodeEnum.D0008); + + // 获取并验证账号 + var user = await GetLoginUser(input.TenantId, account: input.Account); + + // 是否开启域登录验证 + if (await _sysConfigService.GetConfigValueByCode(ConfigConst.SysDomainLogin)) + { + var userLdap = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.UserId == user.Id && u.TenantId == user.TenantId); + if (userLdap == null) + { + VerifyPassword(input.Password, keyPasswordErrorTimes, passwordErrorTimes, user); + } + else if (!await App.GetRequiredService().AuthAccount(user.TenantId, userLdap.Account, CryptogramUtil.Decrypt(input.Password))) + { + _sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); + throw Oops.Oh(ErrorCodeEnum.D1000); + } + } + else + VerifyPassword(input.Password, keyPasswordErrorTimes, passwordErrorTimes, user); + + // 登录成功则清空密码错误次数 + _sysCacheService.Remove(keyPasswordErrorTimes); + + return await CreateToken(user); + } + + /// + /// 获取登录用户 + /// + /// + /// + /// + /// [NonAction] - public async Task GetLoginUser(long tenantId, string account = null, string phone = null) - { - //// 若没有传值租户Id,则从请求页URL参数中获取租户Id(空则默认租户) - //if (tenantId < 1) - //{ - // var tenantidStr = _httpContextAccessor.HttpContext.Request.Query["tenantid"].ToString(); - // tenantId = string.IsNullOrWhiteSpace(tenantidStr) ? SqlSugarConst.DefaultTenantId : long.Parse(tenantidStr); - //} - - // 判断账号是否存在 + public async Task GetLoginUser(long tenantId, string account = null, string phone = null) + { + //// 若没有传值租户Id,则从请求页URL参数中获取租户Id(空则默认租户) + //if (tenantId < 1) + //{ + // var tenantidStr = _httpContextAccessor.HttpContext.Request.Query["tenantid"].ToString(); + // tenantId = string.IsNullOrWhiteSpace(tenantidStr) ? SqlSugarConst.DefaultTenantId : long.Parse(tenantidStr); + //} + + // 判断账号是否存在 var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).ClearFilter() //.WhereIF(tenantId > 0, u => u.TenantId == tenantId) - .WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account)) - .WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone)) - .FirstAsync(); - _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009); - - // 判断账号是否被冻结 - if (user.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.D1017); - - // 判断租户是否存在及状态 - var tenant = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.Id == user.TenantId); - if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003); - - return user; - } - - /// - /// 验证用户密码 - /// - /// - /// - /// - /// - private void VerifyPassword(string password, string keyPasswordErrorTimes, int passwordErrorTimes, SysUser user) - { - // 国密SM2解密(前端密码传输SM2加密后的) - try - { - password = CryptogramUtil.SM2Decrypt(password); - } - catch - { - throw Oops.Oh(ErrorCodeEnum.D0010); - } - - if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString()) - { - if (user.Password.Equals(MD5Encryption.Encrypt(password))) return; - } - else - { - if (CryptogramUtil.Decrypt(user.Password).Equals(password)) return; - } - - _sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); - throw Oops.Oh(ErrorCodeEnum.D1000); - } - - /// - /// 验证锁屏密码 🔖 - /// - /// - /// + .WhereIF(!string.IsNullOrWhiteSpace(account), u => u.Account.Equals(account)) + .WhereIF(!string.IsNullOrWhiteSpace(phone), u => u.Phone.Equals(phone)) + .FirstAsync(); + _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009); + + // 判断账号是否被冻结 + if (user.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.D1017); + + // 判断租户是否存在及状态 + var tenant = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.Id == user.TenantId); + if (tenant?.Status != StatusEnum.Enable) throw Oops.Oh(ErrorCodeEnum.Z1003); + + return user; + } + + /// + /// 验证用户密码 + /// + /// + /// + /// + /// + private void VerifyPassword(string password, string keyPasswordErrorTimes, int passwordErrorTimes, SysUser user) + { + // 国密SM2解密(前端密码传输SM2加密后的) + try + { + password = CryptogramUtil.SM2Decrypt(password); + } + catch + { + throw Oops.Oh(ErrorCodeEnum.D0010); + } + + if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString()) + { + if (user.Password.Equals(MD5Encryption.Encrypt(password))) return; + } + else + { + if (CryptogramUtil.Decrypt(user.Password).Equals(password)) return; + } + + _sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); + throw Oops.Oh(ErrorCodeEnum.D1000); + } + + /// + /// 验证锁屏密码 🔖 + /// + /// + /// [DisplayName("验证锁屏密码")] - public virtual async Task UnLockScreen([Required, FromQuery] string password) - { - // 账号是否存在 - var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId); - _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009); - - var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}"; - var passwordErrorTimes = _sysCacheService.Get(keyPasswordErrorTimes); - - // 是否开启域登录验证 - if (await _sysConfigService.GetConfigValueByCode(ConfigConst.SysDomainLogin)) - { - var userLdap = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.UserId == user.Id && u.TenantId == user.TenantId); - if (userLdap == null) - { - VerifyPassword(password, keyPasswordErrorTimes, passwordErrorTimes, user); - } - else if (!await App.GetRequiredService().AuthAccount(user.TenantId.Value, userLdap.Account, CryptogramUtil.Decrypt(password))) - { - _sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); - throw Oops.Oh(ErrorCodeEnum.D1000); - } - } - else - VerifyPassword(password, keyPasswordErrorTimes, passwordErrorTimes, user); - - return true; - } - - /// - /// 手机号登录 🔖 - /// - /// - /// - [DisplayName("手机号登录")] + public virtual async Task UnLockScreen([Required, FromQuery] string password) + { + // 账号是否存在 + var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId); + _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009); + + var keyPasswordErrorTimes = $"{CacheConst.KeyPasswordErrorTimes}{user.Account}"; + var passwordErrorTimes = _sysCacheService.Get(keyPasswordErrorTimes); + + // 是否开启域登录验证 + if (await _sysConfigService.GetConfigValueByCode(ConfigConst.SysDomainLogin)) + { + var userLdap = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.UserId == user.Id && u.TenantId == user.TenantId); + if (userLdap == null) + { + VerifyPassword(password, keyPasswordErrorTimes, passwordErrorTimes, user); + } + else if (!await App.GetRequiredService().AuthAccount(user.TenantId.Value, userLdap.Account, CryptogramUtil.Decrypt(password))) + { + _sysCacheService.Set(keyPasswordErrorTimes, ++passwordErrorTimes, TimeSpan.FromMinutes(30)); + throw Oops.Oh(ErrorCodeEnum.D1000); + } + } + else + VerifyPassword(password, keyPasswordErrorTimes, passwordErrorTimes, user); + + return true; + } + + /// + /// 手机号登录 🔖 + /// + /// + /// + [DisplayName("手机号登录")] [AllowAnonymous] - public virtual async Task LoginPhone([Required] LoginPhoneInput input) - { - // 校验短信验证码 - App.GetRequiredService().VerifyCode(new SmsVerifyCodeInput { Phone = input.Phone, Code = input.Code }); - - // 获取并验证账号 - var user = await GetLoginUser(input.TenantId, phone: input.Phone); - - return await CreateToken(user); - } - - /// - /// 生成Token令牌 🔖 - /// - /// - /// - /// + public virtual async Task LoginPhone([Required] LoginPhoneInput input) + { + // 校验短信验证码 + App.GetRequiredService().VerifyCode(new SmsVerifyCodeInput { Phone = input.Phone, Code = input.Code }); + + // 获取并验证账号 + var user = await GetLoginUser(input.TenantId, phone: input.Phone); + + return await CreateToken(user); + } + + /// + /// 生成Token令牌 🔖 + /// + /// + /// + /// [NonAction] - public async Task CreateToken(SysUser user, LoginModeEnum loginMode = LoginModeEnum.PC) - { - // 单用户登录 - await App.GetRequiredService().SingleLogin(user.Id, loginMode); - - // 生成Token令牌 - var tokenExpire = await _sysConfigService.GetTokenExpire(); - var accessToken = JWTEncryption.Encrypt(new Dictionary - { - { ClaimConst.UserId, user.Id }, - { ClaimConst.TenantId, user.TenantId }, - { ClaimConst.Account, user.Account }, - { ClaimConst.RealName, user.RealName }, - { ClaimConst.AccountType, user.AccountType }, - { ClaimConst.OrgId, user.OrgId }, - { ClaimConst.OrgName, user.SysOrg?.Name }, - { ClaimConst.OrgType, user.SysOrg?.Type }, - { ClaimConst.OrgLevel, user.SysOrg?.Level }, - { ClaimConst.TokenVersion, user.TokenVersion }, - }, tokenExpire); - - // 生成刷新Token令牌 - var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire(); - var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); - - // 设置响应报文头 - _httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken); - - // Swagger Knife4UI-AfterScript登录脚本 - // ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']); - - // 更新用户登录信息 - user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true); - (user.LastLoginAddress, double? longitude, double? latitude) = CommonUtil.GetIpAddress(user.LastLoginIp); - user.LastLoginTime = DateTime.Now; + public async Task CreateToken(SysUser user, LoginModeEnum loginMode = LoginModeEnum.PC) + { + // 单用户登录 + await App.GetRequiredService().SingleLogin(user.Id, loginMode); + + // 生成Token令牌 + var tokenExpire = await _sysConfigService.GetTokenExpire(); + var accessToken = JWTEncryption.Encrypt(new Dictionary + { + { ClaimConst.UserId, user.Id }, + { ClaimConst.TenantId, user.TenantId }, + { ClaimConst.Account, user.Account }, + { ClaimConst.RealName, user.RealName }, + { ClaimConst.AccountType, user.AccountType }, + { ClaimConst.OrgId, user.OrgId }, + { ClaimConst.OrgName, user.SysOrg?.Name }, + { ClaimConst.OrgType, user.SysOrg?.Type }, + { ClaimConst.OrgLevel, user.SysOrg?.Level }, + { ClaimConst.TokenVersion, user.TokenVersion }, + }, tokenExpire); + + // 生成刷新Token令牌 + var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire(); + var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); + + // 设置响应报文头 + _httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken); + + // Swagger Knife4UI-AfterScript登录脚本 + // ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']); + + // 更新用户登录信息 + user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true); + (user.LastLoginAddress, double? longitude, double? latitude) = CommonUtil.GetIpAddress(user.LastLoginIp); + user.LastLoginTime = DateTime.Now; user.LastLoginDevice = CommonUtil.GetClientDeviceInfo(_httpContextAccessor.HttpContext?.Request?.Headers?.UserAgent); - await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new - { - u.LastLoginIp, - u.LastLoginAddress, - u.LastLoginTime, - u.LastLoginDevice, + await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new + { + u.LastLoginIp, + u.LastLoginAddress, + u.LastLoginTime, + u.LastLoginDevice, }).ExecuteCommandAsync(); // 缓存用户Token版本 _sysCacheService.Set($"{CacheConst.KeyUserToken}{user.Id}", $"{user.TokenVersion}"); // 发布系统登录事件 - await _eventPublisher.PublishAsync(UserEventTypeEnum.Login, user); - - return new LoginOutput - { - AccessToken = accessToken, - RefreshToken = refreshToken - }; - } - - /// - /// 获取登录账号 🔖 - /// - /// + await _eventPublisher.PublishAsync(UserEventTypeEnum.Login, user); + + return new LoginOutput + { + AccessToken = accessToken, + RefreshToken = refreshToken + }; + } + + /// + /// 获取登录账号 🔖 + /// + /// [DisplayName("获取登录账号")] - public virtual async Task GetUserInfo() - { - var user = await _sysUserRep.GetByIdAsync(_userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401); - // 机构 - var org = await _sysUserRep.ChangeRepository>().GetByIdAsync(user.OrgId); - // 职位 - var pos = await _sysUserRep.ChangeRepository>().GetByIdAsync(user.PosId); - // 角色集合 - var roleIds = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync(); - // 接口集合 + public virtual async Task GetUserInfo() + { + var user = await _sysUserRep.GetByIdAsync(_userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401); + // 机构 + var org = await _sysUserRep.ChangeRepository>().GetByIdAsync(user.OrgId); + // 职位 + var pos = await _sysUserRep.ChangeRepository>().GetByIdAsync(user.PosId); + // 角色集合 + var roleIds = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync(); + // 接口集合 var apis = (await App.GetRequiredService().GetUserApiList())[0]; - // 个性化水印文字(若系统水印为空则不显示) - var watermarkText = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.Id == user.TenantId).Select(u => u.Watermark).FirstAsync(); - if (!string.IsNullOrWhiteSpace(watermarkText)) - watermarkText += $"-{user.RealName}"; // $"-{user.RealName}-{_httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true)}-{DateTime.Now}"; - - return new LoginUserOutput - { - Id = user.Id, - TenantId = user.TenantId, - Account = user.Account, - RealName = user.RealName, - Phone = user.Phone, - IdCardNum = user.IdCardNum, - Email = user.Email, - AccountType = user.AccountType, - Avatar = user.Avatar, - Address = user.Address, - Signature = user.Signature, - OrgId = user.OrgId, - OrgName = org?.Name, - OrgType = org?.Type, - PosName = pos?.Name, - Apis = apis, - RoleIds = roleIds, - WatermarkText = watermarkText, - LastChangePasswordTime = user.LastChangePasswordTime - }; - } - - ///// - ///// 获取刷新Token 🔖 - ///// - ///// - ///// - //[DisplayName("获取刷新Token")] - //public string GetRefreshToken([FromQuery] string accessToken) - //{ - // var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult(); - // return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); - //} - - /// - /// 退出系统 🔖 - /// + // 个性化水印文字(若系统水印为空则不显示) + var watermarkText = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.Id == user.TenantId).Select(u => u.Watermark).FirstAsync(); + if (!string.IsNullOrWhiteSpace(watermarkText)) + watermarkText += $"-{user.RealName}"; // $"-{user.RealName}-{_httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true)}-{DateTime.Now}"; + + return new LoginUserOutput + { + Id = user.Id, + TenantId = user.TenantId, + Account = user.Account, + RealName = user.RealName, + Phone = user.Phone, + IdCardNum = user.IdCardNum, + Email = user.Email, + AccountType = user.AccountType, + Avatar = user.Avatar, + Address = user.Address, + Signature = user.Signature, + OrgId = user.OrgId, + OrgName = org?.Name, + OrgType = org?.Type, + PosName = pos?.Name, + Apis = apis, + RoleIds = roleIds, + WatermarkText = watermarkText, + LastChangePasswordTime = user.LastChangePasswordTime + }; + } + + ///// + ///// 获取刷新Token 🔖 + ///// + ///// + ///// + //[DisplayName("获取刷新Token")] + //public string GetRefreshToken([FromQuery] string accessToken) + //{ + // var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult(); + // return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); + //} + + /// + /// 退出系统 🔖 + /// [DisplayName("退出系统")] - public async void Logout() - { + public async void Logout() + { var httpContext = _httpContextAccessor.HttpContext ?? throw Oops.Oh(ErrorCodeEnum.D1016); var accessToken = httpContext.Request.Headers.Authorization.ToString(); @@ -354,74 +354,74 @@ public class SysAuthService : IDynamicApiController, ITransient _sysCacheService.Set($"{CacheConst.KeyTokenBlacklist}:{accessToken}", _userManager.Account, TimeSpan.FromMinutes(tokenExpire)); // 发布系统退出事件 - await _eventPublisher.PublishAsync(UserEventTypeEnum.Logout, _userManager); - - // 退出Swagger/设置无效Token响应头 - _httpContextAccessor.HttpContext.SignoutToSwagger(); - } - - /// - /// 获取验证码 🔖 - /// - /// - [SuppressMonitor] - [DisplayName("获取验证码")] + await _eventPublisher.PublishAsync(UserEventTypeEnum.Logout, _userManager); + + // 退出Swagger/设置无效Token响应头 + _httpContextAccessor.HttpContext.SignoutToSwagger(); + } + + /// + /// 获取验证码 🔖 + /// + /// + [SuppressMonitor] + [DisplayName("获取验证码")] [AllowAnonymous] - public CaptchaOutput GetCaptcha() - { - var codeId = YitIdHelper.NextId().ToString(); - var captcha = _captcha.Generate(codeId); - var expirySeconds = App.GetOptions()?.ExpirySeconds ?? 60; - return new CaptchaOutput { Id = codeId, Img = captcha.Base64, ExpirySeconds = expirySeconds }; - } - - /// - /// Swagger登录检查 🔖 - /// - /// - [Route("/api/swagger/checkUrl"), NonUnify] - [ApiDescriptionSettings(Description = "Swagger登录检查", DisableInherite = true)] + public CaptchaOutput GetCaptcha() + { + var codeId = YitIdHelper.NextId().ToString(); + var captcha = _captcha.Generate(codeId); + var expirySeconds = App.GetOptions()?.ExpirySeconds ?? 60; + return new CaptchaOutput { Id = codeId, Img = captcha.Base64, ExpirySeconds = expirySeconds }; + } + + /// + /// Swagger登录检查 🔖 + /// + /// + [Route("/api/swagger/checkUrl"), NonUnify] + [ApiDescriptionSettings(Description = "Swagger登录检查", DisableInherite = true)] [AllowAnonymous] - public int SwaggerCheckUrl() - { - return _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated ? 200 : 401; - } - - /// - /// Swagger登录提交 🔖 - /// - /// - /// - [Route("/api/swagger/submitUrl"), NonUnify] - [ApiDescriptionSettings(Description = "Swagger登录提交", DisableInherite = true)] + public int SwaggerCheckUrl() + { + return _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated ? 200 : 401; + } + + /// + /// Swagger登录提交 🔖 + /// + /// + /// + [Route("/api/swagger/submitUrl"), NonUnify] + [ApiDescriptionSettings(Description = "Swagger登录提交", DisableInherite = true)] [AllowAnonymous] - public async Task SwaggerSubmitUrl([FromForm] SpecificationAuth auth) - { - try - { - // 关闭默认租户验证码验证 - var tenantList = _sysCacheService.Get>(CacheConst.KeyTenant); + public async Task SwaggerSubmitUrl([FromForm] SpecificationAuth auth) + { + try + { + // 关闭默认租户验证码验证 + var tenantList = _sysCacheService.Get>(CacheConst.KeyTenant); var tenant = tenantList.FirstOrDefault(u => u.Id == SqlSugarConst.DefaultTenantId); - var tmpCaptcha = tenant.Captcha; - tenant.Captcha = false; - _sysCacheService.Set(CacheConst.KeyTenant, tenantList); - - await Login(new LoginInput - { - Account = auth.UserName, - Password = CryptogramUtil.SM2Encrypt(auth.Password), - TenantId = SqlSugarConst.DefaultTenantId - }); - - // 恢复默认租户验证码状态 - tenant.Captcha = tmpCaptcha; - _sysCacheService.Set(CacheConst.KeyTenant, tenantList); - - return 200; - } - catch (Exception) - { - return 401; - } - } + var tmpCaptcha = tenant.Captcha; + tenant.Captcha = false; + _sysCacheService.Set(CacheConst.KeyTenant, tenantList); + + await Login(new LoginInput + { + Account = auth.UserName, + Password = CryptogramUtil.SM2Encrypt(auth.Password), + TenantId = SqlSugarConst.DefaultTenantId + }); + + // 恢复默认租户验证码状态 + tenant.Captcha = tmpCaptcha; + _sysCacheService.Set(CacheConst.KeyTenant, tenantList); + + return 200; + } + catch (Exception) + { + return 401; + } + } } \ No newline at end of file