using Azure.Cosmos; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Logging; using StackExchange.Redis; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using TEAMModelOS.Models; using TEAMModelOS.SDK.DI; using TEAMModelOS.SDK.Models.Table; using static TEAMModelOS.SDK.Models.Teacher; namespace TEAMModelOS.SDK.Models.Service { public static class LoginService { /// /// //添加用户登录信息和在线登录 /// /// 学校 /// 登录类型Teacher Student TmdUser /// 登录者的ID /// 登陆者的IP地址 /// redis /// table表 /// cosmosDB数据库连接 /// 到期时间 /// 上次登录地址 /// public static async Task> DoLoginInfo(List loginInfos, string school, string scope, string id, string ip, AzureRedisFactory _azureRedis, AzureStorageFactory _azureStorage, int expire = 1, string region = null) { var table = _azureStorage.GetCloudTableClient().GetTableReference("IESLogin"); DateTimeOffset dateTime = DateTimeOffset.UtcNow; var dateHour = dateTime.ToString("yyyyMMddHH"); //获取当天的小时 var dateDay = dateTime.ToString("yyyyMMdd"); //获取当天的日期 var dateMonth = dateTime.ToString("yyyyMM");//获取当月的日期 var currentHour = dateTime.Hour; var currentDay = dateTime.Day; long Expire = dateTime.AddHours(expire).ToUnixTimeMilliseconds(); //token到期时间 long now = dateTime.ToUnixTimeMilliseconds(); //时间戳 DateTime hour = DateTime.UtcNow.AddHours(25); //25小时到期 DateTime month = DateTime.UtcNow.AddDays(32); //一个月到期 if (loginInfos.Any()) { if (loginInfos.Count() >= 5) { loginInfos = loginInfos.OrderBy(x => x.expire).ToList(); loginInfos.RemoveRange(4, loginInfos.Count() - 4); } loginInfos.Add(new LoginInfo { expire = Expire, ip = ip, time = now }); } else loginInfos = new List { new LoginInfo { expire = Expire, ip = ip, time = now } }; await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateDay}", $"{currentHour}", 1);//一天24小时 await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:IES:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的累计 var resDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateDay}"); if (resDay == null) { await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateDay}", hour); //设置到期时间 } var rspMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:IES:{scope}:{dateMonth}"); if (rspMonth == null) { await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:IES:{scope}:{dateMonth}", month); //设置到期时间 } ////查询Redis是否有值 //var dayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateDay}"); //List dayCounts = new(); //if (dayCnt != null && dayCnt.Length > 0) //{ // foreach (var hourCnt in dayCnt) // { // dayCounts.Add(new { code = hourCnt.Element.ToString(), count = (int)hourCnt.Score }); // } //} //var monthCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:IES:{scope}:{dateMonth}"); //List monthCounts = new(); //if (monthCnt != null && monthCnt.Length > 0) //{ // foreach (var mCnt in monthCnt) // { // monthCounts.Add(new { code = mCnt.Element.ToString(), count = (int)mCnt.Score }); // } //} //保存当天每小时的峰值 List hourLogins = await table.QueryWhereString($"PartitionKey eq 'HourLogin' and RowKey eq '{dateHour}'"); if (hourLogins.Count > 0) { foreach (var hourLogin in hourLogins) { //hourLogin.Hour = currentHour; if (scope.Equals("teacher")) hourLogin.Teacher += 1; else if (scope.Equals("student")) hourLogin.Student += 1; else hourLogin.TmdUser += 1; } try { await table.SaveOrUpdateAll(hourLogins); } catch { } } else { HourLogin hourLogin = new() { PartitionKey = $"HourLogin", RowKey = dateHour, Hour = currentHour }; if (scope.Equals("teacher")) { hourLogin.Teacher = 1; hourLogin.Student = 0; hourLogin.TmdUser = 0; } else if (scope.Equals("student")) { hourLogin.Teacher = 0; hourLogin.Student = 1; hourLogin.TmdUser = 0; } else { hourLogin.Teacher = 0; hourLogin.Student = 0; hourLogin.TmdUser = 1; } try { await table.SaveOrUpdate(hourLogin);//保存在线数据 } catch { } } //保存当天的峰值 List dayLogins = await table.QueryWhereString($"PartitionKey eq 'DayLogin' and RowKey eq '{dateDay}'"); if (dayLogins.Count > 0) { foreach (var dayLogin in dayLogins) { //dayLogin.Day = currentDay; if (scope.Equals("teacher")) dayLogin.Teacher += 1; else if (scope.Equals("student")) dayLogin.Student += 1; else dayLogin.TmdUser += 1; } try { await table.SaveOrUpdateAll(dayLogins); } catch { } } else { //保存当月每天的峰值 DayLogin dayLogin = new() { PartitionKey = $"DayLogin", RowKey = dateDay, Day = currentDay }; if (scope.Equals("teacher")) { dayLogin.Teacher = 1; dayLogin.Student = 0; dayLogin.TmdUser = 0; } else if (scope.Equals("student")) { dayLogin.Teacher = 0; dayLogin.Student = 1; dayLogin.TmdUser = 0; } else { dayLogin.Teacher = 0; dayLogin.Student = 0; dayLogin.TmdUser = 1; } await table.SaveOrUpdate(dayLogin);//保存在线数据 } if (!string.IsNullOrWhiteSpace(school)) { await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateDay}", $"{currentHour}", 1);//当天当前小时在线人加1 await _azureRedis.GetRedisClient(8).SortedSetIncrementAsync($"Login:School:{school}:{scope}:{dateMonth}", $"{currentDay}", 1); //当天的在线加1 var reScDay = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateDay}"); if (reScDay == null) { await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateDay}", hour); //设置到期时间 } var reScMonth = await _azureRedis.GetRedisClient(8).KeyTimeToLiveAsync($"Login:School:{school}:{scope}:{dateMonth}"); if (reScMonth == null) { await _azureRedis.GetRedisClient(8).KeyExpireAsync($"Login:School:{school}:{scope}:{dateMonth}", month); //设置到期时间 } ////查询Redis是否有值 //var scDayCnt = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateDay}"); //List scDayCounts = new(); //if (scDayCnt != null && scDayCnt.Length > 0) //{ // foreach (var itemHour in scDayCnt) // { // scDayCounts.Add(new { code = itemHour.Element.ToString(), count = (int)itemHour.Score }); // } //} //var ScMonth = _azureRedis.GetRedisClient(8).SortedSetRangeByScoreWithScores($"Login:School:{school}:{scope}:{dateMonth}"); //List scMonthCount = new(); //if (ScMonth != null && ScMonth.Length > 0) //{ // foreach (var count in ScMonth) // { // scMonthCount.Add(new { code = count.Element.ToString(), count = (int)count.Score }); // } //} //保存学校当天每小时的 List hourLoginSchools = await table.QueryWhereString($"PartitionKey eq 'HourLogin-{school}' and RowKey eq '{dateHour}'"); if (hourLoginSchools.Count > 0) { foreach (var hLoginSc in hourLoginSchools) { //hLoginSc.Hour = currentHour; if (scope.Equals("teacher")) hLoginSc.Teacher += 1; else if (scope.Equals("student")) hLoginSc.Student += 1; else hLoginSc.TmdUser += 1; } try { await table.SaveOrUpdateAll(hourLoginSchools); } catch { } } else { //学校小时峰值 HourLoginSchool hourLoginSc = new() { PartitionKey = $"HourLogin-{school}", RowKey = dateHour, Hour = currentHour, School = school }; if (scope.Equals("teacher")) { hourLoginSc.Teacher = 1; hourLoginSc.Student = 0; hourLoginSc.TmdUser = 0; } else if (scope.Equals("student")) { hourLoginSc.Teacher = 0; hourLoginSc.Student = 1; hourLoginSc.TmdUser = 0; } else { hourLoginSc.Teacher = 0; hourLoginSc.Student = 0; hourLoginSc.TmdUser = 1; } try { await table.SaveOrUpdate(hourLoginSc);//保存在线数据 } catch { } } //学校天峰值 List DayLoginSchools = await table.QueryWhereString($"PartitionKey eq 'DayLogin-{school}' and RowKey eq '{dateDay}'"); if (DayLoginSchools.Count > 0) { foreach (var dLoginSc in DayLoginSchools) { //dLoginSc.Day = currentDay; if (scope.Equals("teacher")) dLoginSc.Teacher += 1; else if (scope.Equals("student")) dLoginSc.Student += 1; else dLoginSc.TmdUser += 1; } try { await table.SaveOrUpdateAll(DayLoginSchools); } catch { } } else { //学校天峰值 DayLoginSchool dayLoginSc = new() { PartitionKey = $"DayLogin-{school}", RowKey = dateDay, Day = currentDay, School = school }; if (scope.Equals("teacher")) { dayLoginSc.Teacher = 1; dayLoginSc.Student = 0; dayLoginSc.TmdUser = 0; } else if (scope.Equals("student")) { dayLoginSc.Teacher = 0; dayLoginSc.Student = 1; dayLoginSc.TmdUser = 0; } else { dayLoginSc.Teacher = 0; dayLoginSc.Student = 0; dayLoginSc.TmdUser = 1; } try { await table.SaveOrUpdate(dayLoginSc);//保存在线数据 } catch { } } } return loginInfos; } public static async Task<(string ip, string region)> LoginIp(HttpContext httpContext, IPSearcher _searcher) { var IpPort = httpContext.Request.Headers["X-Forwarded-For"].FirstOrDefault(); if (string.IsNullOrEmpty(IpPort)) { IpPort = httpContext.Connection.RemoteIpAddress.ToString(); } if (IpPort.Contains("::")) { IpPort = "127.0.0.1"; } string ip = IpPort.Split(":")[0]; string region = await _searcher.SearchIpAsync(ip); region= region.Replace("中国·", "").Replace("中国","").Replace("台湾省", "台湾"); return (ip, region); } public static void LoginLog(HttpContext httpContext, Option _option, ILogger _logger, DingDing _dingDing, string ip, string region, string id, string name, int status) { httpContext.Request.Headers.TryGetValue("referer", out var referer); httpContext.Request.Headers.TryGetValue("sec-ch-ua", out var chua); httpContext.Request.Headers.TryGetValue("sec-ch-ua-platform", out var platform); httpContext.Request.Headers.TryGetValue("user-agent", out var useragent); if (status == 200) { string msg = $"{_option.Location} -- {name}({id}):Login Succeed! --Time:{DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")} " + $"--Browser Info( --referer:{referer} --sec-ch-ua:{chua} --sec-ch-ua-platform:{platform} --user-agent:{useragent} --ip:{ip} --region:{region} )"; _logger.LogInformation(msg); } else { string msg = $"{_option.Location} -- {name}({id}):Login Failed! --Time:{DateTimeOffset.UtcNow.ToString("yyyy-MM-dd HH:mm:ss")} " + $"--Browser Info( --referer:{referer} --sec-ch-ua:{chua} --sec-ch-ua-platform:{platform} --user-agent:{useragent} --ip:{ip} --region:{region} )"; _ = _dingDing.SendBotMsg($"IES5,{_option.Location},{msg}", GroupNames.醍摩豆服務運維群組); _logger.LogError(msg); } } } }