SysAuthService.cs 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  1. // 麻省理工学院许可证
  2. //
  3. // 版权所有 (c) 2021-2023 zuohuaijun,大名科技(天津)有限公司 联系电话/微信:18020030720 QQ:515096995
  4. //
  5. // 特此免费授予获得本软件的任何人以处理本软件的权利,但须遵守以下条件:在所有副本或重要部分的软件中必须包括上述版权声明和本许可声明。
  6. //
  7. // 软件按“原样”提供,不提供任何形式的明示或暗示的保证,包括但不限于对适销性、适用性和非侵权的保证。
  8. // 在任何情况下,作者或版权持有人均不对任何索赔、损害或其他责任负责,无论是因合同、侵权或其他方式引起的,与软件或其使用或其他交易有关。
  9. using Furion.SpecificationDocument;
  10. using Lazy.Captcha.Core;
  11. using Microsoft.Extensions.Caching.Memory;
  12. namespace Admin.NET.Core.Service;
  13. /// <summary>
  14. /// 系统登录授权服务
  15. /// </summary>
  16. [ApiDescriptionSettings(Order = 500)]
  17. public class SysAuthService : IDynamicApiController, ITransient
  18. {
  19. private readonly UserManager _userManager;
  20. private readonly SqlSugarRepository<SysUser> _sysUserRep;
  21. private readonly IHttpContextAccessor _httpContextAccessor;
  22. private readonly SysMenuService _sysMenuService;
  23. private readonly SysOnlineUserService _sysOnlineUserService;
  24. private readonly SysConfigService _sysConfigService;
  25. private readonly ICaptcha _captcha;
  26. public SysAuthService(UserManager userManager,
  27. SqlSugarRepository<SysUser> sysUserRep,
  28. IHttpContextAccessor httpContextAccessor,
  29. SysMenuService sysMenuService,
  30. SysOnlineUserService sysOnlineUserService,
  31. SysConfigService sysConfigService,
  32. ICaptcha captcha)
  33. {
  34. _userManager = userManager;
  35. _sysUserRep = sysUserRep;
  36. _httpContextAccessor = httpContextAccessor;
  37. _sysMenuService = sysMenuService;
  38. _sysOnlineUserService = sysOnlineUserService;
  39. _sysConfigService = sysConfigService;
  40. _captcha = captcha;
  41. }
  42. /// <summary>
  43. /// 登录系统
  44. /// </summary>
  45. /// <param name="input"></param>
  46. /// <remarks>用户名/密码:superadmin/123456</remarks>
  47. /// <returns></returns>
  48. [AllowAnonymous]
  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().Includes(t => t.SysOrg).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 != null && 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. var tokenExpire = await _sysConfigService.GetTokenExpire();
  85. var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire();
  86. // 生成Token令牌
  87. var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
  88. {
  89. { ClaimConst.UserId, user.Id },
  90. { ClaimConst.TenantId, user.TenantId },
  91. { ClaimConst.Account, user.Account },
  92. { ClaimConst.RealName, user.RealName },
  93. { ClaimConst.AccountType, user.AccountType },
  94. { ClaimConst.OrgId, user.OrgId },
  95. { ClaimConst.OrgName, user.SysOrg?.Name },
  96. { ClaimConst.OrgType, user.SysOrg?.OrgType },
  97. }, tokenExpire);
  98. // 生成刷新Token令牌
  99. var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
  100. // 设置响应报文头
  101. _httpContextAccessor.HttpContext.SetTokensOfResponseHeaders(accessToken, refreshToken);
  102. // Swagger Knife4UI-AfterScript登录脚本
  103. // ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']);
  104. return new LoginOutput
  105. {
  106. AccessToken = accessToken,
  107. RefreshToken = refreshToken
  108. };
  109. }
  110. /// <summary>
  111. /// 获取登录账号
  112. /// </summary>
  113. /// <returns></returns>
  114. [DisplayName("登录系统")]
  115. public async Task<LoginUserOutput> GetUserInfo()
  116. {
  117. var user = await _sysUserRep.GetFirstAsync(u => u.Id == _userManager.UserId);
  118. if (user == null)
  119. throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401);
  120. // 获取机构
  121. var org = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysOrg>>().GetFirstAsync(u => u.Id == user.OrgId);
  122. // 获取职位
  123. var pos = await _sysUserRep.ChangeRepository<SqlSugarRepository<SysPos>>().GetFirstAsync(u => u.Id == user.PosId);
  124. // 获取拥有按钮权限集合
  125. var buttons = await _sysMenuService.GetOwnBtnPermList();
  126. return new LoginUserOutput
  127. {
  128. Account = user.Account,
  129. RealName = user.RealName,
  130. Avatar = user.Avatar,
  131. Address = user.Address,
  132. Signature = user.Signature,
  133. OrgId = user.OrgId,
  134. OrgName = org?.Name,
  135. OrgType = org?.OrgType,
  136. PosName = pos?.Name,
  137. Buttons = buttons
  138. };
  139. }
  140. /// <summary>
  141. /// 获取刷新Token
  142. /// </summary>
  143. /// <param name="accessToken"></param>
  144. /// <returns></returns>
  145. [DisplayName("获取刷新Token")]
  146. public string GetRefreshToken(string accessToken)
  147. {
  148. var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult();
  149. return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
  150. }
  151. /// <summary>
  152. /// 退出系统
  153. /// </summary>
  154. [DisplayName("退出系统")]
  155. public void Logout()
  156. {
  157. if (string.IsNullOrWhiteSpace(_userManager.Account))
  158. throw Oops.Oh(ErrorCodeEnum.D1011);
  159. _httpContextAccessor.HttpContext.SignoutToSwagger();
  160. }
  161. /// <summary>
  162. /// 获取登录配置
  163. /// </summary>
  164. /// <returns></returns>
  165. [AllowAnonymous]
  166. [SuppressMonitor]
  167. [DisplayName("获取登录配置")]
  168. public async Task<dynamic> GetLoginConfig()
  169. {
  170. var secondVerEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysSecondVer);
  171. var captchaEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysCaptcha);
  172. return new { SecondVerEnabled = secondVerEnabled, CaptchaEnabled = captchaEnabled };
  173. }
  174. /// <summary>
  175. /// 获取用户配置
  176. /// </summary>
  177. /// <returns></returns>
  178. [SuppressMonitor]
  179. [DisplayName("获取用户配置")]
  180. public async Task<dynamic> GetUserConfig()
  181. {
  182. //返回用户和通用配置
  183. var watermarkEnabled = await _sysConfigService.GetConfigValue<bool>(CommonConst.SysWatermark);
  184. return new { WatermarkEnabled = watermarkEnabled };
  185. }
  186. /// <summary>
  187. /// 获取验证码
  188. /// </summary>
  189. /// <returns></returns>
  190. [AllowAnonymous]
  191. [SuppressMonitor]
  192. [DisplayName("获取验证码")]
  193. public dynamic GetCaptcha()
  194. {
  195. var codeId = YitIdHelper.NextId();
  196. var captcha = _captcha.Generate(codeId.ToString());
  197. return new { Id = codeId, Img = captcha.Base64 };
  198. }
  199. /// <summary>
  200. /// swagger登录检查
  201. /// </summary>
  202. /// <returns></returns>
  203. [AllowAnonymous]
  204. [HttpPost("/api/swagger/checkUrl"), NonUnify]
  205. [DisplayName("swagger登录检查")]
  206. public int SwaggerCheckUrl()
  207. {
  208. return _httpContextAccessor.HttpContext.User.Identity.IsAuthenticated ? 200 : 401;
  209. }
  210. /// <summary>
  211. /// swagger登录提交
  212. /// </summary>
  213. /// <param name="auth"></param>
  214. /// <returns></returns>
  215. [AllowAnonymous]
  216. [HttpPost("/api/swagger/submitUrl"), NonUnify]
  217. [DisplayName("swagger登录提交")]
  218. public async Task<int> SwaggerSubmitUrl([FromForm] SpecificationAuth auth)
  219. {
  220. try
  221. {
  222. await Login(new LoginInput
  223. {
  224. Password = auth.Password,
  225. Account = auth.UserName
  226. });
  227. return 200;
  228. }
  229. catch (Exception)
  230. {
  231. return 401;
  232. }
  233. }
  234. }