LoginService.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. using Azure.Cosmos;
  2. using Microsoft.AspNetCore.Http;
  3. using Microsoft.Extensions.Logging;
  4. using StackExchange.Redis;
  5. using System;
  6. using System.Collections.Generic;
  7. using System.Linq;
  8. using System.Text;
  9. using System.Threading.Tasks;
  10. using TEAMModelOS.Models;
  11. using TEAMModelOS.SDK.DI;
  12. using TEAMModelOS.SDK.Models.Table;
  13. using static TEAMModelOS.SDK.Models.Teacher;
  14. namespace TEAMModelOS.SDK.Models.Service
  15. {
  16. public static class LoginService
  17. {
  18. /// <summary>
  19. /// //添加用户登录信息和在线登录
  20. /// </summary>
  21. /// <param name="school">学校</param>
  22. /// <param name="scope">登录类型Teacher Student TmdUser</param>
  23. /// <param name="id">登录者的ID</param>
  24. /// <param name="ip">登陆者的IP地址</param>
  25. /// <param name="_azureRedis">redis</param>
  26. /// <param name="_azureStorage">table表</param>
  27. /// <param name="client">cosmosDB数据库连接</param>
  28. /// <param name="expire">到期时间</param>
  29. /// <param name="region">上次登录地址</param>
  30. /// <returns></returns>
  31. public static async Task<List<LoginInfo>> DoLoginInfo(List<LoginInfo> loginInfos, string school, string scope, string id, string ip, AzureRedisFactory _azureRedis, AzureStorageFactory _azureStorage, CosmosClient client ,int expire =1, string region = null)
  32. {
  33. var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin");
  34. DateTimeOffset dateTime = DateTimeOffset.UtcNow;
  35. var dateHour = dateTime.ToString("yyyyMMddHH"); //获取当天的小时
  36. var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期
  37. var dateMonth = dateTime.ToString("yyyyMM");//获取当月的日期
  38. var currentHour = dateTime.Hour;
  39. var currentDay = dateTime.Day;
  40. long Expire = dateTime.AddHours(expire).ToUnixTimeMilliseconds(); //token到期时间
  41. long now = dateTime.ToUnixTimeMilliseconds(); //时间戳
  42. DateTime hour = DateTime.UtcNow.AddHours(25); //25小时到期
  43. DateTime month = DateTime.UtcNow.AddDays(32); //一个月到期
  44. if (loginInfos.Any())
  45. {
  46. if (loginInfos.Count() >= 5)
  47. {
  48. loginInfos = loginInfos.OrderBy(x => x.expire).ToList();
  49. loginInfos.RemoveRange(4, loginInfos.Count() - 4);
  50. }
  51. loginInfos.Add(new LoginInfo { expire = Expire, ip = ip, time = now });
  52. }
  53. else
  54. loginInfos = new List<LoginInfo> { new LoginInfo { expire = Expire, ip = ip, time = now } };
  55. if (!string.IsNullOrWhiteSpace(school))
  56. {
  57. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateDay}", $"{currentHour}", 1);//当天当前小时在线人加1
  58. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的在线加1
  59. var resDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateDay}");
  60. if (resDay == null)
  61. {
  62. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateDay}", hour); //设置到期时间
  63. }
  64. var rspMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateMonth}");
  65. if (rspMonth != null)
  66. {
  67. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateMonth}", month); //设置到期时间
  68. }
  69. var scDay = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateDay}");
  70. List<dynamic> scDayCount = new();
  71. if (scDay != null && scDay.Length > 0)
  72. {
  73. foreach (var count in scDay)
  74. {
  75. scDayCount.Add(new { code = count.Element.ToString(), count = (int)count.Score });
  76. }
  77. }
  78. //学校小时峰值
  79. HourLoginSchool hourLoginSc = new() { PartitionKey = $"HourLogin-{school}", RowKey = now.ToString(), Hour = int.Parse(dateHour), School = school };
  80. if (scope.Equals("teacher"))
  81. {
  82. hourLoginSc.Teacher = int.Parse(id);
  83. hourLoginSc.Student = 0;
  84. }
  85. else if (scope.Equals("student"))
  86. {
  87. hourLoginSc.Teacher = 0;
  88. hourLoginSc.Student = int.Parse(id);
  89. }
  90. try
  91. {
  92. await table.SaveOrUpdate<HourLoginSchool>(hourLoginSc);//保存在线数据
  93. }
  94. catch
  95. {
  96. }
  97. var ScMonth = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateMonth}");
  98. List<dynamic> scMonthCount = new();
  99. if (ScMonth != null && ScMonth.Length > 0)
  100. {
  101. foreach (var count in ScMonth)
  102. {
  103. scMonthCount.Add(new { code = count.Element.ToString(), count = (int)count.Score });
  104. }
  105. }
  106. //学校天峰值
  107. DayLoginSchool dayLoginSc = new() { PartitionKey = $"DayLogin-{school}", RowKey = now.ToString(), Day = int.Parse(dateDay), School = school };
  108. if (scope.Equals("teacher"))
  109. {
  110. dayLoginSc.Teacher = int.Parse(id);
  111. dayLoginSc.Student = 0;
  112. }
  113. else if (scope.Equals("student"))
  114. {
  115. dayLoginSc.Teacher = 0;
  116. dayLoginSc.Student = int.Parse(id);
  117. }
  118. try
  119. {
  120. await table.SaveOrUpdate<DayLoginSchool>(dayLoginSc);//保存在线数据
  121. }
  122. catch
  123. {
  124. }
  125. }
  126. else
  127. {
  128. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateDay}", $"{currentHour}", 1);//一天24小时
  129. await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的累计
  130. var resDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateDay}");
  131. if (resDay == null)
  132. {
  133. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateDay}", hour); //设置到期时间
  134. }
  135. var rspMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateMonth}");
  136. if (rspMonth == null)
  137. {
  138. await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateMonth}", month); //设置到期时间
  139. }
  140. var scDay = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateDay}");
  141. List<dynamic> scDayCount = new();
  142. if (scDay != null && scDay.Length > 0)
  143. {
  144. foreach (var count in scDay)
  145. {
  146. scDayCount.Add(new { code = count.Element.ToString(), count = (int)count.Score });
  147. }
  148. }
  149. var ScMonth = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateMonth}");
  150. List<dynamic> scMonthCount = new();
  151. if (ScMonth != null && ScMonth.Length > 0)
  152. {
  153. foreach (var count in ScMonth)
  154. {
  155. scMonthCount.Add(new { code = count.Element.ToString(), count = (int)count.Score });
  156. }
  157. }
  158. //个人或者TMDuser小时峰值
  159. HourLogin hourLogin = new() { PartitionKey = $"HourLogin", RowKey = now.ToString(), Hour = int.Parse(dateHour) };
  160. if (scope.Equals("teacher"))
  161. {
  162. hourLogin.Teacher = int.Parse(id);
  163. hourLogin.Student = 0;
  164. hourLogin.TmdUser = 0;
  165. }
  166. else if (scope.Equals("student"))
  167. {
  168. hourLogin.Teacher = 0;
  169. hourLogin.Student = int.Parse(id);
  170. hourLogin.TmdUser = 0;
  171. }
  172. else
  173. {
  174. hourLogin.Teacher = 0;
  175. hourLogin.Student = 0;
  176. hourLogin.TmdUser = int.Parse(id);
  177. }
  178. try
  179. {
  180. await table.SaveOrUpdate<HourLogin>(hourLogin);//保存在线数据
  181. }
  182. catch
  183. {
  184. }
  185. //个人或者TMDuser天峰值
  186. DayLogin dayLogin = new() { PartitionKey = $"DayLogin", RowKey = now.ToString(), Day = int.Parse(dateDay) };
  187. if (scope.Equals("teacher"))
  188. {
  189. dayLogin.Teacher = int.Parse(id);
  190. dayLogin.Student = 0;
  191. dayLogin.TmdUser = 0;
  192. }
  193. else if (scope.Equals("student"))
  194. {
  195. dayLogin.Teacher = 0;
  196. dayLogin.Student = int.Parse(id);
  197. dayLogin.TmdUser = 0;
  198. }
  199. else
  200. {
  201. dayLogin.Teacher = 0;
  202. dayLogin.Student = 0;
  203. dayLogin.TmdUser = int.Parse(id);
  204. }
  205. await table.SaveOrUpdate<DayLogin>(dayLogin);//保存在线数据
  206. }
  207. return loginInfos;
  208. }
  209. public static async Task<(string ip, string region)> LoginIp(HttpContext httpContext, IPSearcher _searcher)
  210. {
  211. var IpPort = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault();
  212. if (string.IsNullOrEmpty(IpPort))
  213. {
  214. IpPort = httpContext.Connection.RemoteIpAddress.ToString();
  215. }
  216. if (IpPort.Contains("::"))
  217. {
  218. IpPort = "127.0.0.1";
  219. }
  220. string ip = IpPort.Split(":")[0];
  221. string region = await _searcher.SearchIpAsync(ip);
  222. return (ip, region);
  223. }
  224. public static void LoginLog(HttpContext httpContext, Option _option, ILogger _logger, DingDing _dingDing, string ip, string region, string id, string name, int status)
  225. {
  226. httpContext.Request.Headers.TryGetValue("referer", out var referer);
  227. httpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua);
  228. httpContext.Request.Headers.TryGetValue("sec-ch-ua-platform", out var platform);
  229. httpContext.Request.Headers.TryGetValue("user-agent", out var useragent);
  230. if (status == 200)
  231. {
  232. string msg = $"{_option.Location} -- {name}({id}):Login Succeed! --Time:{DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")} " +
  233. $"--Browser Info( --referer:{referer} --sec-ch-ua:{chua} --sec-ch-ua-platform:{platform} --user-agent:{useragent} --ip:{ip} --region:{region} )";
  234. _logger.LogInformation(msg);
  235. }
  236. else
  237. {
  238. string msg = $"{_option.Location} -- {name}({id}):Login Failed! --Time:{DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")} " +
  239. $"--Browser Info( --referer:{referer} --sec-ch-ua:{chua} --sec-ch-ua-platform:{platform} --user-agent:{useragent} --ip:{ip} --region:{region} )";
  240. _ = _dingDing.SendBotMsg($"IES5,{_option.Location},{msg}", GroupNames.醍摩豆服務運維群組);
  241. _logger.LogError(msg);
  242. }
  243. }
  244. }
  245. }