Sic.Framework-Nanjing-Baishi/MECF.Framework.Common/Aitex/Core/Account/CredentialManager.cs

331 lines
9.1 KiB
C#
Raw Normal View History

using System;
using System.Collections.Generic;
using System.Linq;
using Aitex.Core.RT.Event;
using Aitex.Core.Util;
namespace Aitex.Core.Account;
/// <summary>
/// 登录凭据管理器。
/// </summary>
public class CredentialManager : Singleton<CredentialManager>
{
#region Variables
private const int KEEP_ALIVE_TIMEOUT_SEC = 60;
private readonly object _syncRoot = new();
/// <summary>
/// 已登录的凭据。
/// </summary>
private readonly Dictionary<Guid, Credential> _dictCredentialsLoggedIn = new ();
/// <summary>
/// 正在等在登录请求确认的凭据。
/// </summary>
private readonly Dictionary<Guid, Credential> _dictCredentialsRequesting = new ();
private readonly PeriodicJob _threadMonitorCred;
private bool _isInitialized;
private int _maxCredentialAllowed;
#endregion
#region Constructors
/// <summary>
/// 登录凭据管理的构造函数。
/// </summary>
public CredentialManager()
{
_threadMonitorCred = new(1000, OnTimer, "CredentialAliveMonitorThread", true, true);
}
#endregion
#region Properties
/// <summary>
/// 返回当前凭据管理器是否支持多用户登录。
/// </summary>
public bool IsSupportMultiUserLogin => _maxCredentialAllowed > 1;
/// <summary>
/// 返回已登录的用户凭据的数量。
/// </summary>
public int LoggedInCount
{
get
{
lock (_syncRoot)
{
return _dictCredentialsLoggedIn.Count;
}
}
}
#endregion
#region Methods
/// <summary>
/// 初始化登录凭据管理器。
/// </summary>
/// <param name="isSupportMultiUsersLogin">是否支持多用户同时登录。</param>
public void Initialize(bool isSupportMultiUsersLogin)
{
if (_isInitialized)
throw new InvalidOperationException($"{nameof(CredentialManager)} has been initialized.");
_isInitialized = true;
_maxCredentialAllowed = isSupportMultiUsersLogin ? int.MaxValue : 1;
}
private bool OnTimer()
{
lock (_syncRoot)
{
var removableList = new List<Guid>();
foreach (var kvp in _dictCredentialsLoggedIn)
{
var cred = kvp.Value;
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > KEEP_ALIVE_TIMEOUT_SEC)
EV.PostLoginBySameUser(cred.Token, new Credential());
}
if (removableList.Count > 0)
{
foreach (var token in removableList)
_dictCredentialsLoggedIn.Remove(token);
}
removableList.Clear();
foreach (var kvp in _dictCredentialsRequesting)
{
var cred = kvp.Value;
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > KEEP_ALIVE_TIMEOUT_SEC)
removableList.Add(kvp.Key);
}
if (removableList.Count > 0)
{
foreach (var token in removableList)
_dictCredentialsRequesting.Remove(token);
}
}
return true;
}
/// <summary>
/// 检查指定的用户名是否已经登录。
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
internal bool IsLoggedIn(string userName)
{
lock (_syncRoot)
{
return _dictCredentialsLoggedIn.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName) != null;
}
}
/// <summary>
/// 检查指定令牌的登录凭据是否存在。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
internal bool IsLoggedIn(Guid token)
{
lock (_syncRoot)
{
return _dictCredentialsLoggedIn.ContainsKey(token);
}
}
/// <summary>
/// 检查指定的令牌是否已经过期。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
internal bool IsTokenExpired(Guid token)
{
lock (_syncRoot)
{
return _dictCredentialsLoggedIn.ContainsKey(token);
}
}
/// <summary>
/// 报告客户端处于活动状态。
/// </summary>
/// <param name="token">客户端登录凭据令牌。</param>
/// <returns></returns>
public CredentialKeepAliveResults KeepAlive(Guid token)
{
lock (_syncRoot)
{
if (_dictCredentialsLoggedIn.TryGetValue(token, out var cred))
{
cred.LastAliveTime = DateTime.Now; // 刷新时间
return CredentialKeepAliveResults.Alived;
}
return CredentialKeepAliveResults.NotFound;
}
}
/// <summary>
/// 将凭据加入请求列表。
/// </summary>
/// <param name="cred"></param>
/// <exception cref="InvalidOperationException"></exception>
public void AddRequestingList(Credential cred)
{
lock (_syncRoot)
{
if (_dictCredentialsRequesting.ContainsKey(cred.Token))
throw new InvalidOperationException("the credential has been existed in requesting list.");
_dictCredentialsRequesting[cred.Token] = cred;
}
}
/// <summary>
/// 将指定的凭据加入字典。
/// </summary>
/// <param name="cred">待授权的凭据</param>
/// <remarks>
/// 给凭据授权前必须调用<see cref="AddRequestingList"/>方法将凭据加入到等待列表中。
/// </remarks>
/// <exception cref="Exception"></exception>
public void Grant(Credential cred)
{
if (IsLoggedIn(cred.AccountInfo.LoginName))
throw new Exception($"user {cred.AccountInfo.LoginName} has been logged in.");
lock (_syncRoot)
{
if (_dictCredentialsLoggedIn.Count >= _maxCredentialAllowed)
throw new InvalidOperationException("maximum number of login credentials reached");
if (!_dictCredentialsRequesting.ContainsKey(cred.Token))
throw new InvalidOperationException("the credential is not found in requesting list.");
cred.State = CredentialState.Alive;
_dictCredentialsLoggedIn[cred.Token] = cred;
_dictCredentialsRequesting.Remove(cred.Token);
}
}
/// <summary>
/// 移除指定令牌的凭据。
/// </summary>
/// <param name="token"></param>
public void Remove(Guid token)
{
lock (_syncRoot)
{
_dictCredentialsLoggedIn.Remove(token);
}
}
/// <summary>
/// 从登录请求列表中移除指定的凭据。
/// </summary>
/// <param name="cred"></param>
public void RemoveRequesting(Credential cred)
{
lock (_syncRoot)
{
_dictCredentialsRequesting.Remove(cred.Token);
}
}
/// <summary>
/// 获取指定用户名的登录凭据。
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public Credential GetCredential(string userName)
{
lock (_syncRoot)
{
return _dictCredentialsLoggedIn.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName);
}
}
/// <summary>
/// 获取指定用户名的登录凭据。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public Credential GetCredential(Guid token)
{
lock (_syncRoot)
{
return _dictCredentialsLoggedIn.TryGetValue(token, out var cred) ? cred : null;
}
}
/// <summary>
/// 获取指定用户名的正在等在登录请求的凭据。
/// </summary>
/// <param name="userName">用户名</param>
/// <returns></returns>
public Credential GetRequestingCredential(string userName)
{
lock (_syncRoot)
{
return _dictCredentialsRequesting.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName);
}
}
/// <summary>
/// 获取指定令牌的正在等在登录请求的凭据。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public Credential GetRequestingCredential(Guid token)
{
lock (_syncRoot)
{
return _dictCredentialsRequesting.TryGetValue(token, out var cred) ? cred : null;
}
}
/// <summary>
/// 校验指定令牌的凭据是否有效。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public bool ValidateCredential(Guid token)
{
lock (_syncRoot)
{
if (_dictCredentialsLoggedIn.TryGetValue(token, out var cred))
{
return cred.State == CredentialState.Alive;
}
return false;
}
}
#endregion
#region Static Methods
/// <summary>
/// 创建一个令牌。
/// </summary>
/// <returns></returns>
public static Guid GenerateToken()
{
return Guid.NewGuid();
}
#endregion
}