SysAuthService.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. using Furion.SpecificationDocument;
  2. using Lazy.Captcha.Core;
  3. using Microsoft.AspNetCore.Authentication;
  4. using Microsoft.Extensions.Caching.Memory;
  5. namespace Admin.NET.Core.Service;
  6. /// <summary>
  7. /// 系统登录授权服务
  8. /// </summary>
  9. [ApiDescriptionSettings(Order = 500)]
  10. public class SysAuthService : IDynamicApiController, ITransient
  11. {
  12. private readonly UserManager _userManager;
  13. private readonly SqlSugarRepository<SysUser> _sysUserRep;
  14. private readonly RefreshTokenOptions _refreshTokenOptions;
  15. private readonly IHttpContextAccessor _httpContextAccessor;
  16. private readonly SysMenuService _sysMenuService;
  17. private readonly SysOnlineUserService _sysOnlineUserService;
  18. private readonly SysConfigService _sysConfigService;
  19. private readonly IMemoryCache _cache;
  20. private readonly ICaptcha _captcha;
  21. public SysAuthService(UserManager userManager,
  22. SqlSugarRepository<SysUser> sysUserRep,
  23. IOptions<RefreshTokenOptions> refreshTokenOptions,
  24. IHttpContextAccessor httpContextAccessor,
  25. SysMenuService sysMenuService,
  26. SysOnlineUserService sysOnlineUserService,
  27. SysConfigService sysConfigService,
  28. IMemoryCache cache,
  29. ICaptcha captcha)
  30. {
  31. _userManager = userManager;
  32. _sysUserRep = sysUserRep;
  33. _httpContextAccessor = httpContextAccessor;
  34. _refreshTokenOptions = refreshTokenOptions.Value;
  35. _sysMenuService = sysMenuService;
  36. _sysOnlineUserService = sysOnlineUserService;
  37. _sysConfigService = sysConfigService;
  38. _cache = cache;
  39. _captcha = captcha;
  40. }
  41. /// <summary>
  42. /// 登录系统
  43. /// </summary>
  44. /// <param name="input"></param>
  45. /// <remarks>用户名/密码:superadmin/123456</remarks>
  46. /// <returns></returns>
  47. [AllowAnonymous]
  48. [ApiDescriptionSettings(Name = "Login")]
  49. [DisplayName("登录系统")]
  50. public async Task<LoginOutput> Login([Required] LoginInput input)
  51. {
  52. //// 可以根据域名获取具体租户
  53. //var host = _httpContextAccessor.HttpContext.Request.Host;
  54. // 是否开启验证码
  55. if (await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha))
  56. {
  57. // 判断验证码
  58. if (!_captcha.Validate(input.CodeId.ToString(), input.Code))
  59. throw Oops.Oh(ErrorCodeEnum.D0008);
  60. }
  61. // 账号是否存在
  62. var user = await _sysUserRep.AsQueryable().Filter(null, true).FirstAsync(u => u.Account.Equals(input.Account));
  63. _ = user ?? throw Oops.Oh(ErrorCodeEnum.D0009);
  64. // 账号是否被冻结
  65. if (user.Status == StatusEnum.Disable)
  66. throw Oops.Oh(ErrorCodeEnum.D1017);
  67. // 租户是否被禁用
  68. var tenant = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysTenant>>().GetFirstAsync(u => u.Id == user.TenantId);
  69. if (tenant.Status == StatusEnum.Disable)
  70. throw Oops.Oh(ErrorCodeEnum.Z1003);
  71. // 密码是否正确
  72. if (CryptogramUtil.CryptoType == CryptogramEnum.MD5.ToString())
  73. {
  74. if (user.Password != MD5Encryption.Encrypt(input.Password))
  75. throw Oops.Oh(ErrorCodeEnum.D1000);
  76. }
  77. else
  78. {
  79. if (CryptogramUtil.Decrypt(user.Password) != input.Password)
  80. throw Oops.Oh(ErrorCodeEnum.D1000);
  81. }
  82. // 单用户登录
  83. await _sysOnlineUserService.SignleLogin(user.Id);
  84. // 生成Token令牌
  85. var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
  86. {
  87. {ClaimConst.UserId, user.Id},
  88. {ClaimConst.TenantId, user.TenantId},
  89. {ClaimConst.Account, user.Account},
  90. {ClaimConst.RealName, user.RealName},
  91. {ClaimConst.AccountType, user.AccountType },
  92. {ClaimConst.OrgId, user.OrgId},
  93. });
  94. // 生成刷新Token令牌
  95. var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, _refreshTokenOptions.ExpiredTime);
  96. // 设置响应报文头
  97. _httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken);
  98. // Swagger Knife4UI-AfterScript登录脚本
  99. // ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']);
  100. return new LoginOutput
  101. {
  102. AccessToken = accessToken,
  103. RefreshToken = refreshToken
  104. };
  105. }
  106. /// <summary>
  107. /// 获取登录账号
  108. /// </summary>
  109. /// <returns></returns>
  110. [ApiDescriptionSettings(Name = "UserInfo")]
  111. [DisplayName("登录系统")]
  112. public async Task<LoginUserOutput> GetUserInfo()
  113. {
  114. var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId);
  115. if (user == null)
  116. throw Oops.Oh(ErrorCodeEnum.D1011);
  117. // 获取机构
  118. var org = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysOrg>>().GetFirstAsync(u => u.Id == user.OrgId);
  119. // 获取职位
  120. var pos = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysPos>>().GetFirstAsync(u => u.Id == user.PosId);
  121. // 获取拥有按钮权限集合
  122. var buttons = await _sysMenuService.GetOwnBtnPermList();
  123. return new LoginUserOutput
  124. {
  125. Account = user.Account,
  126. RealName = user.RealName,
  127. Avatar = user.Avatar,
  128. Address = user.Address,
  129. Signature = user.Signature,
  130. OrgId = user.OrgId,
  131. OrgName = org?.Name,
  132. PosName = pos?.Name,
  133. Buttons = buttons
  134. };
  135. }
  136. /// <summary>
  137. /// 获取刷新Token
  138. /// </summary>
  139. /// <param name="accessToken"></param>
  140. /// <returns></returns>
  141. [ApiDescriptionSettings(Name = "RefreshToken")]
  142. [DisplayName("获取刷新Token")]
  143. public string GetRefreshToken([Required] string accessToken)
  144. {
  145. return JWTEncryption.GenerateRefreshToken(accessToken, _refreshTokenOptions.ExpiredTime);
  146. }
  147. /// <summary>
  148. /// 退出系统
  149. /// </summary>
  150. [ApiDescriptionSettings(Name = "Logout")]
  151. [DisplayName("退出系统")]
  152. public async Task LogoutAsync()
  153. {
  154. if (string.IsNullOrWhiteSpace(_userManager.Account))
  155. throw Oops.Oh(ErrorCodeEnum.D1011);
  156. _httpContextAccessor.HttpContext.SignoutToSwagger();
  157. await _httpContextAccessor.HttpContext.SignOutAsync();
  158. }
  159. /// <summary>
  160. /// 获取登录配置
  161. /// </summary>
  162. /// <returns></returns>
  163. [AllowAnonymous]
  164. [SuppressMonitor]
  165. [ApiDescriptionSettings(Name = "LoginConfig")]
  166. [DisplayName("获取登录配置")]
  167. public async Task<dynamic> GetLoginConfig()
  168. {
  169. var secondVerEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSecondVer);
  170. var captchaEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha);
  171. var wartermarkEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysWartermark);
  172. return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled, WartermarkEnabled = wartermarkEnabled };
  173. }
  174. /// <summary>
  175. /// 获取验证码
  176. /// </summary>
  177. /// <returns></returns>
  178. [AllowAnonymous]
  179. [SuppressMonitor]
  180. [ApiDescriptionSettings(Name = "Captcha")]
  181. [DisplayName("获取验证码")]
  182. public dynamic GetCaptcha()
  183. {
  184. var codeId = YitIdHelper.NextId();
  185. var captcha = _captcha.Generate(codeId.ToString());
  186. return new { Id = codeId, Img = captcha.Base64 };
  187. }
  188. /// <summary>
  189. /// swagger登录检查
  190. /// </summary>
  191. /// <returns></returns>
  192. [AllowAnonymous]
  193. [HttpPost("/api/swagger/checkUrl"), NonUnify]
  194. [DisplayName("swagger登录检查")]
  195. public int SwaggerCheckUrl()
  196. {
  197. return _cache.Get<bool>(CacheConst.SwaggerLogin) ? 200 : 401;
  198. }
  199. /// <summary>
  200. /// swagger登录提交
  201. /// </summary>
  202. /// <param name="auth"></param>
  203. /// <returns></returns>
  204. [AllowAnonymous]
  205. [HttpPost("/api/swagger/submitUrl"), NonUnify]
  206. [DisplayName("swagger登录提交")]
  207. public int SwaggerSubmitUrl([FromForm] SpecificationAuth auth)
  208. {
  209. var userName = App.GetConfig<string>("SpecificationDocumentSettings:LoginInfo:UserName");
  210. var password = App.GetConfig<string>("SpecificationDocumentSettings:LoginInfo:Password");
  211. if (auth.UserName == userName && auth.Password == password)
  212. {
  213. _cache.Set<bool>(CacheConst.SwaggerLogin, true);
  214. return 200;
  215. }
  216. return 401;
  217. }
  218. }