using WingServerCommon.Config; using WingServerCommon.Config.Parameters; using WingServerCommon.Interfaces.Cache; using WingServerCommon.Log; using WingServerCommon.Utilities; namespace WingServerCommon.Interfaces.PasswordVerify { /// /// 登保用户密码过期校验 /// public class PasswordExpireVerify { /// /// send notice 事件 /// public event EventHandler SendNoticeEvent; //待加载数据委托 private Func, IList> _loadDatasFunc; private Queue _dtQueue = new Queue(); //密码更新周期,天数 private int _pwdUpdatePeriod; //提前预警天数 private int _warningDays; //记录密码次数 private int _keepPwdTimes; //预警周期cron表达式,默认频率每天10点触发 private string _verifyPeriodCron; //任务周期 private int _dutyCycle = 1 * 60 * 1000; // AccountType private int _accountType = 0; /// /// 初始化构造 /// public PasswordExpireVerify(Func, IList> loadDatasFunc) { _pwdUpdatePeriod = ConfigurationManager.GetParammeter("Authentication", "PwdUpdatePeriod").Value; if (_pwdUpdatePeriod <= 0) { _pwdUpdatePeriod = 90; } _warningDays = ConfigurationManager.GetParammeter("Authentication", "WarningDays").Value; if (_warningDays <= 0) { _warningDays = 5; } _keepPwdTimes = ConfigurationManager.GetParammeter("Authentication", "KeepPwdTimes").Value; if (_keepPwdTimes <= 0) { _keepPwdTimes = 5; } _verifyPeriodCron = ConfigurationManager.GetParammeter("Authentication", "VerifyPeriodCron").Value; if (string.IsNullOrEmpty(_verifyPeriodCron)) { _verifyPeriodCron = "0 0 10 * * ?"; } _loadDatasFunc = loadDatasFunc; } /// /// 检查用户密码过期监听 /// protected async Task VerifyUserPasswordListen(int type, bool isOpen) { if (isOpen) { var verifyTime = Convert.ToDateTime(CronHelper.GetNextDateTime(_verifyPeriodCron, DateTime.Now)); _dtQueue.Enqueue(verifyTime); _accountType = type; var timer = new System.Timers.Timer(); timer.Elapsed += new System.Timers.ElapsedEventHandler(Verify_Elapsed); timer.Interval = _dutyCycle; timer.Enabled = true; } } /// /// 自定义定时任务 /// /// 用户code列表 /// 发送通知委托 /// 是否成功 private void Verify_Elapsed(object sender, System.Timers.ElapsedEventArgs e) { try { if (_dtQueue.Count > 0) { var verifyTime = _dtQueue.Dequeue();//解析到的时间都是固定的时间点,而不是直接加间隔时间 var curDT = DateTime.Now; var curStartTime = Convert.ToDateTime((curDT.ToString("yyyy-MM-dd HH:mm") + ":00")); var curEndTime = Convert.ToDateTime((curDT.AddMinutes(1).ToString("yyyy-MM-dd HH:mm") + ":00")); //只有特定的时间点,才可以执行监察工作 if (verifyTime != null && verifyTime >= curStartTime && verifyTime < curEndTime) { Logger.WriteLineInfo($"PasswordExpireVerify Begin Run"); //获取所有的在线的Token; var tokenList = CacheMaintenance.Instance.Get().Where(x => x.IsOnline == true && !string.IsNullOrEmpty(x.ClientId) && x.AccountType == _accountType); VerifyPasswordExpire(tokenList); verifyTime = Convert.ToDateTime(CronHelper.GetNextDateTime(_verifyPeriodCron, DateTime.Now)); _dtQueue.Enqueue(verifyTime); Logger.WriteLineInfo($"PasswordExpireVerify End Run"); } else { _dtQueue.Enqueue(verifyTime); } } } catch (Exception ex) { Logger.WriteLineError($"Dispatch VerifyPasswordExpire Error:{ex}"); } } /// /// 在线用户密码是否过期校验,如果过期,则发送通知 /// /// 用户code列表 /// 发送通知委托 /// 是否成功 private void VerifyPasswordExpire(IList tokenList) { var clientIds = new List(); //业务处理逻辑 if (tokenList == null || tokenList.Count <= 0) { return; } // AccountType // "0": "管理员", // "1": "用户", // "2": "超声机", // "3": "超声魔盒", // "4": "合作方", clientIds = tokenList.Select(c => c.ClientId).Distinct().ToList(); //获取数据源 IList dataList = _loadDatasFunc(clientIds); if (dataList != null && dataList.Count > 0) { //找到对应的token信息,发送通知 var args = new SendNoticeArgs(); foreach (var item in dataList) { if (item.PasswordLastUpdateTime < Convert.ToDateTime("2000-1-1")) { continue; } var verifyResult = VerifyData(item.ClientId, item.PasswordLastUpdateTime); args.VerifyList.Add(verifyResult); } if (args.VerifyList?.Count > 0) { //发送成功 SendNoticeEvent?.Invoke(null, args); } } } /// /// 单个用户的验证逻辑 /// /// 用户数据 /// 验证结果 protected VerifyBaseModel VerifyData(string clientId, DateTime lastUpdateTime) { var verifyResult = new VerifyBaseModel() { ClientId = clientId }; //验证逻辑 var expireTime = lastUpdateTime.AddDays(_pwdUpdatePeriod); var warningTime = expireTime.AddDays(-_warningDays); //过期时间跟当前时间比较,如果当前时间>过期时间,表示过期,否则未过期 if (DateTime.UtcNow > expireTime) { //已过期 TimeSpan diffTime = expireTime - DateTime.UtcNow; //分钟转天数 verifyResult.SurplusTime = TransferMinutesToDays(diffTime.TotalMinutes); } //如果过期时间>当前时间,且当前时间>预警时间,则表示需要预警 else if (expireTime > DateTime.UtcNow && DateTime.UtcNow > warningTime) { //即将过期 TimeSpan diffTime = expireTime - warningTime; verifyResult.SurplusTime = TransferMinutesToDays(diffTime.TotalMinutes); } else { //无需预警 } return verifyResult; } /// /// 分钟转天数 /// /// 修改请求数据 /// 是否成功 private double TransferMinutesToDays(double totalMinutes) { double days = 0; //分钟转天数 var surplusTime = totalMinutes / (60f * 24f); if (Math.Abs(surplusTime) < 0.01) { days = surplusTime > 0 ? 0.01 : -0.01; } else { days = Math.Round(surplusTime, 2); } return days; } } /// /// 通知参数 /// public class SendNoticeArgs : EventArgs { /// /// 验证结果列表 /// public IList VerifyList { get; set; } = new List(); } /// /// 密码验证实体 /// public class PasswordVerifyModel { /// /// 用户id /// public string ClientId { get; set; } = string.Empty; /// /// 密码过期时间 /// public DateTime PasswordLastUpdateTime { get; set; } = DateTime.MinValue; /// /// 密码记录 /// public List PasswordRecords { get; set; } = new List(); /// /// 新密码 /// public string NewPassword { get; set; } = string.Empty; } /// /// 验证基础类 /// public class VerifyBaseModel { /// /// 登录用户code /// public string ClientId { get; set; } = string.Empty; /// /// 密码过期剩余时间: 天,可以为负,负责表示已经过期 /// public double SurplusTime { get; set; } = 0; } }