using Furion.SpecificationDocument; using Lazy.Captcha.Core; using Microsoft.Extensions.Caching.Memory; namespace Admin.NET.Core.Service; /// /// 系统登录授权服务 /// [ApiDescriptionSettings(Order = 500)] public class SysAuthService : IDynamicApiController, ITransient { private readonly UserManager _userManager; private readonly SqlSugarRepository _sysUserRep; private readonly IHttpContextAccessor _httpContextAccessor; private readonly SysMenuService _sysMenuService; private readonly SysOnlineUserService _sysOnlineUserService; private readonly SysConfigService _sysConfigService; private readonly IMemoryCache _cache; private readonly ICaptcha _captcha; public SysAuthService(UserManager userManager, SqlSugarRepository sysUserRep, IHttpContextAccessor httpContextAccessor, SysMenuService sysMenuService, SysOnlineUserService sysOnlineUserService, SysConfigService sysConfigService, IMemoryCache cache, ICaptcha captcha) { _userManager = userManager; _sysUserRep = sysUserRep; _httpContextAccessor = httpContextAccessor; _sysMenuService = sysMenuService; _sysOnlineUserService = sysOnlineUserService; _sysConfigService = sysConfigService; _cache = cache; _captcha = captcha; } /// /// 登录系统 /// /// /// 用户名/密码:superadmin/123456 /// [AllowAnonymous] [DisplayName("登录系统")] public async Task Login([Required] LoginInput input) { //// 可以根据域名获取具体租户 //var host = _httpContextAccessor.HttpContext.Request.Host; // 是否开启验证码 if (await _sysConfigService.GetConfigValue(CommonConst.SysCaptcha)) { // 判断验证码 if (!_captcha.Validate(input.CodeId.ToString(), input.Code)) throw Oops.Oh(ErrorCodeEnum.D0008); } // 账号是否存在 var user = await _sysUserRep.AsQueryable().Includes(t => t.SysOrg).Filter(null, true).FirstAsync(u => u.Account.Equals(input.Account)); _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009); // 账号是否被冻结 if (user.Status == StatusEnum.Disable) throw Oops.Oh(ErrorCodeEnum.D1017); // 租户是否被禁用 var tenant = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.Id == user.TenantId); if (tenant != null && tenant.Status == StatusEnum.Disable) throw Oops.Oh(ErrorCodeEnum.Z1003); // 密码是否正确 if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString()) { if (user.Password != MD5Encryption.Encrypt(input.Password)) throw Oops.Oh(ErrorCodeEnum.D1000); } else { if (CryptogramUtil.Decrypt(user.Password) != input.Password) throw Oops.Oh(ErrorCodeEnum.D1000); } // 单用户登录 await _sysOnlineUserService.SignleLogin(user.Id); var tokenExpire = await _sysConfigService.GetTokenExpire(); var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire(); // 生成Token令牌 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 }, }, tokenExpire); // 生成刷新Token令牌 var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); // 设置响应报文头 _httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken); // Swagger Knife4UI-AfterScript登录脚本 // ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']); return new LoginOutput { AccessToken = accessToken, RefreshToken = refreshToken }; } /// /// 获取登录账号 /// /// [DisplayName("登录系统")] public async Task GetUserInfo() { var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId); if (user == null) throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401); // 获取机构 var org = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.Id == user.OrgId); // 获取职位 var pos = await _sysUserRep.ChangeRepository>().GetFirstAsync(u => u.Id == user.PosId); // 获取拥有按钮权限集合 var buttons = await _sysMenuService.GetOwnBtnPermList(); return new LoginUserOutput { Account = user.Account, RealName = user.RealName, Avatar = user.Avatar, Address = user.Address, Signature = user.Signature, OrgId = user.OrgId, OrgName = org?.Name, PosName = pos?.Name, Buttons = buttons }; } /// /// 获取刷新Token /// /// /// [DisplayName("获取刷新Token")] public string GetRefreshToken(string accessToken) { var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult(); return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); } /// /// 退出系统 /// [DisplayName("退出系统")] public void Logout() { if (string.IsNullOrWhiteSpace(_userManager.Account)) throw Oops.Oh(ErrorCodeEnum.D1011); _httpContextAccessor.HttpContext.SignoutToSwagger(); } /// /// 获取登录配置 /// /// [AllowAnonymous] [SuppressMonitor] [DisplayName("获取登录配置")] public async Task GetLoginConfig() { var secondVerEnabled = await _sysConfigService.GetConfigValue(CommonConst.SysSecondVer); var captchaEnabled = await _sysConfigService.GetConfigValue(CommonConst.SysCaptcha); return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled }; } /// /// 获取用户配置 /// /// [SuppressMonitor] [DisplayName("获取用户配置")] public async Task GetUserConfig() { //返回用户和通用配置 var watermarkEnabled = await _sysConfigService.GetConfigValue(CommonConst.SysWatermark); return new { WatermarkEnabled = watermarkEnabled }; } /// /// 获取验证码 /// /// [AllowAnonymous] [SuppressMonitor] [DisplayName("获取验证码")] public dynamic GetCaptcha() { var codeId = YitIdHelper.NextId(); var captcha = _captcha.Generate(codeId.ToString()); return new { Id = codeId, Img = captcha.Base64 }; } /// /// swagger登录检查 /// /// [AllowAnonymous] [HttpPost("/api/swagger/checkUrl"), NonUnify] [DisplayName("swagger登录检查")] public int SwaggerCheckUrl() { return _cache.Get(CacheConst.SwaggerLogin) ? 200 : 401; } /// /// swagger登录提交 /// /// /// [AllowAnonymous] [HttpPost("/api/swagger/submitUrl"), NonUnify] [DisplayName("swagger登录提交")] public int SwaggerSubmitUrl([FromForm] SpecificationAuth auth) { var userName = App.GetConfig("SpecificationDocumentSettings:LoginInfo:UserName"); var password = App.GetConfig("SpecificationDocumentSettings:LoginInfo:Password"); if (auth.UserName == userName && auth.Password == password) { _cache.Set(CacheConst.SwaggerLogin, true); return 200; } return 401; } }