PasswordExpireVerify.cs 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. using WingServerCommon.Config;
  2. using WingServerCommon.Config.Parameters;
  3. using WingServerCommon.Interfaces.Cache;
  4. using WingServerCommon.Log;
  5. using WingServerCommon.Utilities;
  6. namespace WingServerCommon.Interfaces.PasswordVerify
  7. {
  8. /// <summary>
  9. /// 登保用户密码过期校验
  10. /// </summary>
  11. public class PasswordExpireVerify
  12. {
  13. /// <summary>
  14. /// send notice 事件
  15. /// </summary>
  16. public event EventHandler<SendNoticeArgs> SendNoticeEvent;
  17. //待加载数据委托
  18. private Func<IList<string>, IList<PasswordVerifyModel>> _loadDatasFunc;
  19. private Queue<DateTime> _dtQueue = new Queue<DateTime>();
  20. //密码更新周期,天数
  21. private int _pwdUpdatePeriod;
  22. //提前预警天数
  23. private int _warningDays;
  24. //记录密码次数
  25. private int _keepPwdTimes;
  26. //预警周期cron表达式,默认频率每天10点触发
  27. private string _verifyPeriodCron;
  28. //任务周期
  29. private int _dutyCycle = 1 * 60 * 1000;
  30. // AccountType
  31. private int _accountType = 0;
  32. /// <summary>
  33. /// 初始化构造
  34. /// </summary>
  35. public PasswordExpireVerify(Func<IList<string>, IList<PasswordVerifyModel>> loadDatasFunc)
  36. {
  37. _pwdUpdatePeriod = ConfigurationManager.GetParammeter<IntParameter>("Authentication", "PwdUpdatePeriod").Value;
  38. if (_pwdUpdatePeriod <= 0)
  39. {
  40. _pwdUpdatePeriod = 90;
  41. }
  42. _warningDays = ConfigurationManager.GetParammeter<IntParameter>("Authentication", "WarningDays").Value;
  43. if (_warningDays <= 0)
  44. {
  45. _warningDays = 5;
  46. }
  47. _keepPwdTimes = ConfigurationManager.GetParammeter<IntParameter>("Authentication", "KeepPwdTimes").Value;
  48. if (_keepPwdTimes <= 0)
  49. {
  50. _keepPwdTimes = 5;
  51. }
  52. _verifyPeriodCron = ConfigurationManager.GetParammeter<StringParameter>("Authentication", "VerifyPeriodCron").Value;
  53. if (string.IsNullOrEmpty(_verifyPeriodCron))
  54. {
  55. _verifyPeriodCron = "0 0 10 * * ?";
  56. }
  57. _loadDatasFunc = loadDatasFunc;
  58. }
  59. /// <summary>
  60. /// 检查用户密码过期监听
  61. /// </summary>
  62. protected async Task VerifyUserPasswordListen(int type, bool isOpen)
  63. {
  64. if (isOpen)
  65. {
  66. var verifyTime = Convert.ToDateTime(CronHelper.GetNextDateTime(_verifyPeriodCron, DateTime.Now));
  67. _dtQueue.Enqueue(verifyTime);
  68. _accountType = type;
  69. var timer = new System.Timers.Timer();
  70. timer.Elapsed += new System.Timers.ElapsedEventHandler(Verify_Elapsed);
  71. timer.Interval = _dutyCycle;
  72. timer.Enabled = true;
  73. }
  74. }
  75. /// <summary>
  76. /// 自定义定时任务
  77. /// </summary>
  78. /// <param name="clientIdList">用户code列表</param>
  79. /// <param name="sendNoticeFunc">发送通知委托</param>
  80. /// <returns>是否成功</returns>
  81. private void Verify_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
  82. {
  83. try
  84. {
  85. if (_dtQueue.Count > 0)
  86. {
  87. var verifyTime = _dtQueue.Dequeue();//解析到的时间都是固定的时间点,而不是直接加间隔时间
  88. var curDT = DateTime.Now;
  89. var curStartTime = Convert.ToDateTime((curDT.ToString("yyyy-MM-dd HH:mm") + ":00"));
  90. var curEndTime = Convert.ToDateTime((curDT.AddMinutes(1).ToString("yyyy-MM-dd HH:mm") + ":00"));
  91. //只有特定的时间点,才可以执行监察工作
  92. if (verifyTime != null && verifyTime >= curStartTime && verifyTime < curEndTime)
  93. {
  94. Logger.WriteLineInfo($"PasswordExpireVerify Begin Run");
  95. //获取所有的在线的Token;
  96. var tokenList = CacheMaintenance.Instance.Get<ITokensManager>().Where(x => x.IsOnline == true && !string.IsNullOrEmpty(x.ClientId) && x.AccountType == _accountType);
  97. VerifyPasswordExpire(tokenList);
  98. verifyTime = Convert.ToDateTime(CronHelper.GetNextDateTime(_verifyPeriodCron, DateTime.Now));
  99. _dtQueue.Enqueue(verifyTime);
  100. Logger.WriteLineInfo($"PasswordExpireVerify End Run");
  101. }
  102. else
  103. {
  104. _dtQueue.Enqueue(verifyTime);
  105. }
  106. }
  107. }
  108. catch (Exception ex)
  109. {
  110. Logger.WriteLineError($"Dispatch VerifyPasswordExpire Error:{ex}");
  111. }
  112. }
  113. /// <summary>
  114. /// 在线用户密码是否过期校验,如果过期,则发送通知
  115. /// </summary>
  116. /// <param name="clientIdList">用户code列表</param>
  117. /// <param name="sendNoticeFunc">发送通知委托</param>
  118. /// <returns>是否成功</returns>
  119. private void VerifyPasswordExpire(IList<Token> tokenList)
  120. {
  121. var clientIds = new List<string>();
  122. //业务处理逻辑
  123. if (tokenList == null || tokenList.Count <= 0)
  124. {
  125. return;
  126. }
  127. // AccountType
  128. // "0": "管理员",
  129. // "1": "用户",
  130. // "2": "超声机",
  131. // "3": "超声魔盒",
  132. // "4": "合作方",
  133. clientIds = tokenList.Select(c => c.ClientId).Distinct().ToList();
  134. //获取数据源
  135. IList<PasswordVerifyModel> dataList = _loadDatasFunc(clientIds);
  136. if (dataList != null && dataList.Count > 0)
  137. {
  138. //找到对应的token信息,发送通知
  139. var args = new SendNoticeArgs();
  140. foreach (var item in dataList)
  141. {
  142. if (item.PasswordLastUpdateTime < Convert.ToDateTime("2000-1-1"))
  143. {
  144. continue;
  145. }
  146. var verifyResult = VerifyData(item.ClientId, item.PasswordLastUpdateTime);
  147. args.VerifyList.Add(verifyResult);
  148. }
  149. if (args.VerifyList?.Count > 0)
  150. {
  151. //发送成功
  152. SendNoticeEvent?.Invoke(null, args);
  153. }
  154. }
  155. }
  156. /// <summary>
  157. /// 单个用户的验证逻辑
  158. /// </summary>
  159. /// <param name="tokenList">用户数据</param>
  160. /// <returns>验证结果</returns>
  161. protected VerifyBaseModel VerifyData(string clientId, DateTime lastUpdateTime)
  162. {
  163. var verifyResult = new VerifyBaseModel()
  164. {
  165. ClientId = clientId
  166. };
  167. //验证逻辑
  168. var expireTime = lastUpdateTime.AddDays(_pwdUpdatePeriod);
  169. var warningTime = expireTime.AddDays(-_warningDays);
  170. //过期时间跟当前时间比较,如果当前时间>过期时间,表示过期,否则未过期
  171. if (DateTime.UtcNow > expireTime)
  172. {
  173. //已过期
  174. TimeSpan diffTime = expireTime - DateTime.UtcNow;
  175. //分钟转天数
  176. verifyResult.SurplusTime = TransferMinutesToDays(diffTime.TotalMinutes);
  177. }
  178. //如果过期时间>当前时间,且当前时间>预警时间,则表示需要预警
  179. else if (expireTime > DateTime.UtcNow && DateTime.UtcNow > warningTime)
  180. {
  181. //即将过期
  182. TimeSpan diffTime = expireTime - warningTime;
  183. verifyResult.SurplusTime = TransferMinutesToDays(diffTime.TotalMinutes);
  184. }
  185. else
  186. {
  187. //无需预警
  188. }
  189. return verifyResult;
  190. }
  191. /// <summary>
  192. /// 分钟转天数
  193. /// </summary>
  194. /// <param name="request">修改请求数据</param>
  195. /// <returns>是否成功</returns>
  196. private double TransferMinutesToDays(double totalMinutes)
  197. {
  198. double days = 0;
  199. //分钟转天数
  200. var surplusTime = totalMinutes / (60f * 24f);
  201. if (Math.Abs(surplusTime) < 0.01)
  202. {
  203. days = surplusTime > 0 ? 0.01 : -0.01;
  204. }
  205. else
  206. {
  207. days = Math.Round(surplusTime, 2);
  208. }
  209. return days;
  210. }
  211. }
  212. /// <summary>
  213. /// 通知参数
  214. /// </summary>
  215. public class SendNoticeArgs : EventArgs
  216. {
  217. /// <summary>
  218. /// 验证结果列表
  219. /// </summary>
  220. public IList<VerifyBaseModel> VerifyList { get; set; } = new List<VerifyBaseModel>();
  221. }
  222. /// <summary>
  223. /// 密码验证实体
  224. /// </summary>
  225. public class PasswordVerifyModel
  226. {
  227. /// <summary>
  228. /// 用户id
  229. /// </summary>
  230. public string ClientId { get; set; } = string.Empty;
  231. /// <summary>
  232. /// 密码过期时间
  233. /// </summary>
  234. public DateTime PasswordLastUpdateTime { get; set; } = DateTime.MinValue;
  235. /// <summary>
  236. /// 密码记录
  237. /// </summary>
  238. public List<string> PasswordRecords { get; set; } = new List<string>();
  239. /// <summary>
  240. /// 新密码
  241. /// </summary>
  242. public string NewPassword { get; set; } = string.Empty;
  243. }
  244. /// <summary>
  245. /// 验证基础类
  246. /// </summary>
  247. public class VerifyBaseModel
  248. {
  249. /// <summary>
  250. /// 登录用户code
  251. /// </summary>
  252. public string ClientId { get; set; } = string.Empty;
  253. /// <summary>
  254. /// 密码过期剩余时间: 天,可以为负,负责表示已经过期
  255. /// </summary>
  256. public double SurplusTime { get; set; } = 0;
  257. }
  258. }