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;
}
}