using Admin.NET.Core; using Admin.NET.Core.Options; using Furion; using Furion.DatabaseAccessor; using Furion.DataEncryption; using Furion.DependencyInjection; using Furion.DynamicApiController; using Furion.EventBus; using Furion.FriendlyException; using Mapster; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.ComponentModel.DataAnnotations; using UAParser; using Admin.NET.Core.Entity.WmsBase; namespace Admin.NET.Application { /// /// 登录授权相关服务 /// [ApiDescriptionSettings(Name = "Auth", Order = 160)] [Route("api")] public class AuthService : IAuthService, IDynamicApiController, ITransient { private readonly IHttpContextAccessor _httpContextAccessor; private readonly IRepository _sysUserRep; // 用户表仓储 private readonly IRepository _wmsPdaPower; private readonly IRepository _wmsRolePdaMenu; private readonly IRepository _sysDictData; private readonly ISysUserService _sysUserService; // 系统用户服务 private readonly ISysEmpService _sysEmpService; // 系统员工服务 private readonly ISysRoleService _sysRoleService; // 系统角色服务 private readonly ISysMenuService _sysMenuService; // 系统菜单服务 private readonly ISysAppService _sysAppService; // 系统应用服务 private readonly IClickWordCaptcha _captchaHandle; // 验证码服务 private readonly ISysConfigService _sysConfigService; // 验证码服务 private readonly IEventPublisher _eventPublisher; private readonly ISysCacheService _cache; /// /// 构造函数 /// public AuthService(IRepository sysUserRep, IRepository wmsPdaPower, IRepository wmsRolePdaMenu, IRepository sysDictData, IHttpContextAccessor httpContextAccessor, ISysUserService sysUserService, ISysEmpService sysEmpService, ISysRoleService sysRoleService, ISysMenuService sysMenuService, ISysAppService sysAppService, IClickWordCaptcha captchaHandle, ISysConfigService sysConfigService, IEventPublisher eventPublisher, ISysCacheService cache) { _sysUserRep = sysUserRep; _wmsPdaPower = wmsPdaPower; _wmsRolePdaMenu = wmsRolePdaMenu; _sysDictData = sysDictData; _httpContextAccessor = httpContextAccessor; _sysUserService = sysUserService; _sysEmpService = sysEmpService; _sysRoleService = sysRoleService; _sysMenuService = sysMenuService; _sysAppService = sysAppService; _captchaHandle = captchaHandle; _sysConfigService = sysConfigService; _eventPublisher = eventPublisher; _cache = cache; } /// /// 用户登录 /// /// /// 默认用户名/密码:admin/admin /// [HttpPost("login")] [AllowAnonymous] public string LoginAsync([Required] LoginInput input) { // 获取加密后的密码 var encryptPasswod = MD5Encryption.Encrypt(input.Password); // 判断用户名和密码是否正确 忽略全局过滤器 var user = _sysUserRep .Where(u => u.Account.Equals(input.Account) && u.Password.Equals(encryptPasswod) && u.IsDeleted == false, false, true) .FirstOrDefault(); _ = user ?? throw Oops.Oh(ErrorCode.D1000); // 验证账号是否被冻结 if (user.Status == CommonStatus.DISABLE) throw Oops.Oh(ErrorCode.D1017); //验证是否单用户登录,如果是剔除已经登录的用户 if (_sysConfigService.GetEnableSingleLoginFlag().Result) { var onlineUsers = _cache.GetAsync>(CommonConst.CACHE_KEY_ONLINE_USER).Result; if (onlineUsers != null) { var loginuser = onlineUsers.FirstOrDefault(u => u.UserId == user.Id); if (loginuser != null) { App.GetService().SingleLoginForceExist(loginuser); } } } // 员工信息 var empInfo = _sysEmpService.GetEmpInfo(user.Id).Result; // 获取数据权限 var dataScopes = JsonUtil.ToJson(_sysUserService.GetUserDataScopeIdList(user.Id).Result); // 生成Token令牌 //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user); var accessToken = JWTEncryption.Encrypt(new Dictionary { {ClaimConst.CLAINM_USERID, user.Id}, //{ClaimConst.TENANT_ID, user.TenantId}, {ClaimConst.CLAINM_ACCOUNT, user.Account}, {ClaimConst.CLAINM_NAME, user.Name}, {ClaimConst.CLAINM_SUPERADMIN, user.AdminType}, {ClaimConst.CLAINM_ORGID, empInfo.OrgId}, {ClaimConst.CLAINM_ORGNAME, empInfo.OrgName}, {ClaimConst.DATA_SCOPES, dataScopes} }); // 设置Swagger自动登录 _httpContextAccessor.HttpContext.SigninToSwagger(accessToken); var tokenData = JWTEncryption.ReadJwtToken(accessToken); // 解密 //var (isValid, tokenData, validationResult) = JWTEncryption.Validate(accessToken); // 验证token有效期 // 生成刷新Token令牌 var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, App.GetOptions().ExpiredTime); // 设置刷新Token令牌 _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken; return accessToken; } /// /// 获取当前PC登录用户信息 /// /// [HttpGet("getLoginUser")] public async Task GetLoginUserAsync() { var user = _sysUserRep.FirstOrDefault(u => u.Id == CurrentUserInfo.UserId, false); if (user == null) throw Oops.Oh(ErrorCode.D1011); var userId = user.Id; var httpContext = _httpContextAccessor.HttpContext; var loginOutput = user.Adapt(); loginOutput.LastLoginTime = user.LastLoginTime = DateTimeOffset.Now; loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRequestIPv4(); //var ipInfo = IpTool.Search(loginOutput.LastLoginIp); //loginOutput.LastLoginAddress = ipInfo.Country + ipInfo.Province + ipInfo.City + "[" + ipInfo.NetworkOperator + "][" + ipInfo.Latitude + ipInfo.Longitude + "]"; 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.LoginEmpInfo = await _sysEmpService.GetEmpInfo(userId); // 角色信息 loginOutput.Roles = await _sysRoleService.GetUserRoleList(userId); // 权限信息 loginOutput.Permissions = await _sysMenuService.GetLoginPermissionList(userId); // 系统所有权限信息 loginOutput.AllPermissions = await _sysMenuService.GetAllPermissionList(); // 数据范围信息(机构Id集合) loginOutput.DataScopes = await _sysUserService.GetUserDataScopeIdList(userId); // 具备应用信息(多系统,默认激活一个,可根据系统切换菜单),返回的结果中第一个为激活的系统 loginOutput.Apps = await _sysAppService.GetLoginApps(userId); // 菜单信息 if (loginOutput.Apps.Count > 0) { var activeApp = loginOutput.Apps.FirstOrDefault(u => u.Active == YesOrNot.Y.ToString()); var defaultActiveAppCode = activeApp != null ? activeApp.Code : loginOutput.Apps.FirstOrDefault().Code; loginOutput.Menus = await _sysMenuService.GetLoginMenusAntDesign(userId, defaultActiveAppCode); } // 更新用户最后登录Ip和时间 await _sysUserRep.UpdateIncludeAsync(user, new[] { nameof(SysUser.LastLoginIp), nameof(SysUser.LastLoginTime) }); // 增加登录日志 await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog", new SysLogVis { Name = loginOutput.Name, Success = YesOrNot.Y, Message = "登录成功", Ip = loginOutput.LastLoginIp, Browser = loginOutput.LastLoginBrowser, Os = loginOutput.LastLoginOs, VisType = LoginType.LOGIN, VisTime = loginOutput.LastLoginTime, Account = loginOutput.Account })); return loginOutput; } /// /// 获取当前PDA登录用户信息 /// /// [HttpGet("getPdaLoginUser")] public async Task GetPdaLoginUserAsync() { var user = _sysUserRep.FirstOrDefault(u => u.Id == CurrentUserInfo.UserId, false); if (user == null) throw Oops.Oh(ErrorCode.D1011); var userId = user.Id; var httpContext = _httpContextAccessor.HttpContext; var loginOutput = user.Adapt(); loginOutput.LastLoginTime = user.LastLoginTime = DateTimeOffset.Now; loginOutput.LastLoginIp = user.LastLoginIp = httpContext.GetRequestIPv4(); //var ipInfo = IpTool.Search(loginOutput.LastLoginIp); //loginOutput.LastLoginAddress = ipInfo.Country + ipInfo.Province + ipInfo.City + "[" + ipInfo.NetworkOperator + "][" + ipInfo.Latitude + ipInfo.Longitude + "]"; 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; // 角色信息 var roleList = await _sysRoleService.GetUserRoleList(userId); var meunIdList = _wmsRolePdaMenu.Where(n => roleList.Select(u => u.Id).Contains(n.SysRoleId)).Select(n => n.PdaMenuId).ToList(); var wmspdaPowerList = _wmsPdaPower.Where(n => meunIdList.Contains(n.Id)).Adapt>(); var dicDataList = _sysDictData.Where(p => p.TypeId == 383290718294085).ToList(); var listData = new List(); foreach (var item in dicDataList) { var enumValue = LesWorkShopType.FAPAOCHEJIAN; if (item.Code == "1") enumValue = LesWorkShopType.FAPAOCHEJIAN; else if (item.Code == "2") enumValue = LesWorkShopType.JIAOHEBANCHEJIAN; else if (item.Code == "3") enumValue = LesWorkShopType.JHBCJ; else if (item.Code == "4") enumValue = LesWorkShopType.RSBCJ; else if (item.Code == "5") enumValue = LesWorkShopType.YLKCJ; else enumValue = LesWorkShopType.TY; if (wmspdaPowerList.Where(n => n.WorkShopType == enumValue).ToList().Count() != 0) { listData.Add(new wmsPdaPowerMenuOutput() { WorkShopName = item.Value, WmsPdaPowerOutput = wmspdaPowerList.Where(n => n.WorkShopType == enumValue).ToList() }); } } loginOutput.WmsPdaPowerOutputs = listData; // 更新用户最后登录Ip和时间 await _sysUserRep.UpdateIncludeAsync(user, new[] { nameof(SysUser.LastLoginIp), nameof(SysUser.LastLoginTime) }); // 增加登录日志 await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog", new SysLogVis { Name = loginOutput.Name, Success = YesOrNot.Y, Message = "登录成功", Ip = loginOutput.LastLoginIp, Browser = loginOutput.LastLoginBrowser, Os = loginOutput.LastLoginOs, VisType = LoginType.LOGIN, VisTime = loginOutput.LastLoginTime, Account = loginOutput.Account })); return loginOutput; } /// /// 退出 /// /// [HttpGet("logout")] [AllowAnonymous] public async Task LogoutAsync() { 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 = CurrentUserInfo.Name, Success = YesOrNot.Y, Message = "退出成功", VisType = LoginType.LOGOUT, VisTime = DateTimeOffset.Now, Account = CurrentUserInfo.Account, Ip = ip })); } /// /// 获取验证码开关 /// /// [HttpGet("getCaptchaOpen")] [AllowAnonymous] public async Task GetCaptchaOpen() { return await _sysConfigService.GetCaptchaOpenFlag(); } /// /// 获取验证码(默认点选模式) /// /// [HttpPost("captcha/get")] [AllowAnonymous] [NonUnify] public async Task GetCaptcha() { // 图片大小要与前端保持一致(坐标范围) return await _captchaHandle.CreateCaptchaImage(_captchaHandle.RandomCode(4), 310, 155); } /// /// 校验验证码 /// /// /// [HttpPost("captcha/check")] [AllowAnonymous] [NonUnify] public async Task VerificationCode(ClickWordCaptchaInput input) { return await _captchaHandle.CheckCode(input); } } }