using Lazy.Captcha.Core; using Microsoft.Extensions.Options; using NETCore.Encrypt; using ZR.Admin.WebApi.Filters; using ZR.Service.System; using ZR.Service.System.IService; using ZR.ServiceCore.Model; using ZR.ServiceCore.Model.Dto; using ZR.ServiceCore.Services.IService; namespace ZR.Admin.WebApi.Controllers.System { /// /// 登录 /// [ApiExplorerSettings(GroupName = "sys")] public class SysLoginController : BaseController { //static readonly NLog.Logger logger = NLog.LogManager.GetLogger("LoginController"); private readonly IHttpContextAccessor httpContextAccessor; private readonly ISysUserService sysUserService; private readonly ISysMenuService sysMenuService; private readonly ISysLoginService sysLoginService; private readonly ISysPermissionService permissionService; private readonly ICaptcha SecurityCodeHelper; private readonly ISysConfigService sysConfigService; private readonly ISysRoleService roleService; private readonly OptionsSetting optionSettings; public SysLoginController( IHttpContextAccessor contextAccessor, ISysMenuService sysMenuService, ISysUserService sysUserService, ISysLoginService sysLoginService, ISysPermissionService permissionService, ISysConfigService configService, ISysRoleService sysRoleService, ICaptcha captcha, IOptions optionSettings) { httpContextAccessor = contextAccessor; SecurityCodeHelper = captcha; this.sysMenuService = sysMenuService; this.sysUserService = sysUserService; this.sysLoginService = sysLoginService; this.permissionService = permissionService; this.sysConfigService = configService; roleService = sysRoleService; this.optionSettings = optionSettings.Value; } // RSA私钥 private static readonly string PrivatePem = AppSettings.GetConfig("RSA:PrivatePem"); /// /// 登录 /// /// 登录对象 /// [Route("login")] [HttpPost] [Log(Title = "登录")] public IActionResult Login([FromBody] LoginBodyDto loginBody) { if (loginBody == null) { throw new CustomException("请求参数错误"); } loginBody.LoginIP = HttpContextExtension.GetClientUserIp(HttpContext); var sysConfig = sysConfigService.GetSysConfigByKey("sys.account.captchaOnOff"); var headers = HttpContext.Request.Headers; var isRemoteInvoke = headers["Remote-Invoke"].FirstOrDefault().ParseToBool(); if (sysConfig?.ConfigValue != "off" && !SecurityCodeHelper.Validate(loginBody.Uuid, loginBody.Code) && !isRemoteInvoke) { return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误"); } sysLoginService.CheckLockUser(loginBody.Username); string location = HttpContextExtension.GetIpInfo(loginBody.LoginIP); // RSA解密 loginBody.Password = EncryptProvider.RSADecryptWithPem(PrivatePem, loginBody.Password); var user = sysLoginService.Login(loginBody, new SysLogininfor() { LoginLocation = location }); List roles = roleService.SelectUserRoleListByUserId(user.UserId); //权限集合 eg *:*:*,system:user:list List permissions = permissionService.GetMenuPermission(user); TokenModel loginUser = new(user.Adapt(), roles.Adapt>()); CacheService.SetUserPerms(GlobalConstant.UserPermKEY + user.UserId, permissions); return SUCCESS(JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(loginUser))); } /// /// 注销 /// /// [Log(Title = "注销")] [HttpPost("logout")] public IActionResult LogOut() { //Task.Run(async () => //{ // //注销登录的用户,相当于ASP.NET中的FormsAuthentication.SignOut // await HttpContext.SignOutAsync(); //}).Wait(); var userid = HttpContext.GetUId(); var name = HttpContext.GetName(); CacheService.RemoveUserPerms(GlobalConstant.UserPermKEY + userid); return SUCCESS(new { name, id = userid }); } /// /// 获取用户信息 /// /// [Verify] [HttpGet("getInfo")] public IActionResult GetUserInfo() { long userid = HttpContext.GetUId(); var user = sysUserService.SelectUserById(userid); //前端校验按钮权限使用 //角色集合 eg: admin,yunying,common List roles = permissionService.GetRolePermission(user); //权限集合 eg *:*:*,system:user:list List permissions = permissionService.GetMenuPermission(user); user.WelcomeContent = GlobalConstant.WelcomeMessages[new Random().Next(0, GlobalConstant.WelcomeMessages.Length)]; return SUCCESS(new { user, roles, permissions }); } /// /// 获取路由信息 /// /// [Verify] [HttpGet("getRouters")] public IActionResult GetRouters() { long uid = HttpContext.GetUId(); var menus = sysMenuService.SelectMenuTreeByUserId(uid); return SUCCESS(sysMenuService.BuildMenus(menus)); } /// /// 生成图片验证码 /// /// [HttpGet("captchaImage")] public IActionResult CaptchaImage() { string uuid = Guid.NewGuid().ToString().Replace("-", ""); SysConfig sysConfig = sysConfigService.GetSysConfigByKey("sys.account.captchaOnOff"); var captchaOff = sysConfig?.ConfigValue ?? "0"; var info = SecurityCodeHelper.Generate(uuid, 60); var obj = new { captchaOff, uuid, img = info.Base64 };// File(stream, "image/png") return SUCCESS(obj); } /// /// 注册 /// /// /// [HttpPost("/register")] [AllowAnonymous] [Log(Title = "注册", BusinessType = BusinessType.INSERT)] public IActionResult Register([FromBody] RegisterDto dto) { SysConfig config = sysConfigService.GetSysConfigByKey("sys.account.register"); if (config?.ConfigValue != "true") { return ToResponse(ResultCode.CUSTOM_ERROR, "当前系统没有开启注册功能!"); } SysConfig sysConfig = sysConfigService.GetSysConfigByKey("sys.account.captchaOnOff"); if (sysConfig?.ConfigValue != "off" && !SecurityCodeHelper.Validate(dto.Uuid, dto.Code)) { return ToResponse(ResultCode.CAPTCHA_ERROR, "验证码错误"); } SysUser user = sysUserService.Register(dto); if (user.UserId > 0) { return SUCCESS(user); } return ToResponse(ResultCode.CUSTOM_ERROR, "注册失败,请联系管理员"); } #region 二维码登录 /// /// 生成二维码 /// /// /// /// [HttpGet("/GenerateQrcode")] public IActionResult GenerateQrcode(string uuid, string deviceId) { var state = Guid.NewGuid().ToString(); var dict = new Dictionary { { "state", state } }; CacheService.SetScanLogin(uuid, dict); return SUCCESS(new { status = 1, state, uuid, codeContent = new { uuid, deviceId }// "https://qm.qq.com/cgi-bin/qm/qr?k=kgt4HsckdljU0VM-0kxND6d_igmfuPlL&authKey=r55YUbruiKQ5iwC/folG7KLCmZ++Y4rQVgNlvLbUniUMkbk24Y9+zNuOmOnjAjRc&noverify=0" }); } /// /// 轮询判断扫码状态 /// /// /// [HttpPost("/VerifyScan")] [AllowAnonymous] public IActionResult VerifyScan([FromBody] ScanDto dto) { int status = -1; object token = string.Empty; if (CacheService.GetScanLogin(dto.Uuid) is Dictionary str) { status = 0; str.TryGetValue("token", out token); if (str.ContainsKey("status") && (string)str.GetValueOrDefault("status") == "success") { status = 2;//扫码成功 CacheService.RemoveScanLogin(dto.Uuid); } } return SUCCESS(new { status, token }); } /// /// 移动端扫码登录 /// /// /// [HttpPost("/ScanLogin")] [Log(Title = "扫码登录")] [Verify] public IActionResult ScanLogin([FromBody] ScanDto dto) { if (dto == null) { return ToResponse(ResultCode.CUSTOM_ERROR, "扫码失败"); } var name = App.HttpContext.GetName(); sysLoginService.CheckLockUser(name); TokenModel tokenModel = JwtUtil.GetLoginUser(HttpContext); if (CacheService.GetScanLogin(dto.Uuid) is not null) { Dictionary dict = new() { }; dict.Add("status", "success"); dict.Add("token", JwtUtil.GenerateJwtToken(JwtUtil.AddClaims(tokenModel))); CacheService.SetScanLogin(dto.Uuid, dict); return SUCCESS(1); } return ToResponse(ResultCode.FAIL, "二维码已失效"); } #endregion } }