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

208 lines
5.5 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 readonly object _syncRoot = new();
private readonly Dictionary<string, Credential> _dictLoginCredentials = 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 IReadOnlyDictionary<string, Credential> Credentials => _dictLoginCredentials;
#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)
{
foreach (var kvp in _dictLoginCredentials)
{
var cred = kvp.Value;
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > 60)
{
// 如果当前凭据超过60s未激活一次表示客户端可能已经离线移除
cred.State = CredentialState.Expired;
EV.PostLoginBySameUser(cred);
}
}
}
return true;
}
/// <summary>
/// 检查指定的用户名是否已经登录。
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
internal bool CheckHasLoggedIn(string userName)
{
lock (_syncRoot)
{
return _dictLoginCredentials.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName) != null;
}
}
/// <summary>
/// 检查指定令牌的登录凭据是否存在。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
internal bool CheckHasLoggedInByToken(string token)
{
lock (_syncRoot)
{
return _dictLoginCredentials.ContainsKey(token);
}
}
/// <summary>
/// 报告客户端处于活动状态。
/// </summary>
/// <param name="token">客户端登录凭据令牌。</param>
/// <returns></returns>
public CredentialKeepAliveResults KeepAlive(string token)
{
lock (_syncRoot)
{
if (_dictLoginCredentials.TryGetValue(token, out var cred))
{
if (cred.State == CredentialState.Expired)
return CredentialKeepAliveResults.Expired;
cred.LastAliveTime = DateTime.Now; // 刷新时间
return CredentialKeepAliveResults.Alive;
}
return CredentialKeepAliveResults.NotFound;
}
}
/// <summary>
/// 将指定的凭据加入字典。
/// </summary>
/// <param name="cred"></param>
/// <exception cref="Exception"></exception>
public void Add(Credential cred)
{
if (CheckHasLoggedIn(cred.AccountInfo.LoginName))
throw new Exception($"user {cred.AccountInfo.LoginName} has been logged in.");
lock (_syncRoot)
{
if (_dictLoginCredentials.Count >= _maxCredentialAllowed)
throw new InvalidOperationException("maximum number of login credentials reached");
_dictLoginCredentials[cred.Token] = cred;
}
}
/// <summary>
/// 移除指定令牌的凭据。
/// </summary>
/// <param name="token"></param>
public void Remove(string token)
{
lock (_syncRoot)
{
_dictLoginCredentials.Remove(token);
}
}
/// <summary>
/// 获取指定用户名的登录凭据。
/// </summary>
/// <param name="userName"></param>
/// <returns></returns>
public Credential GetCredentialByUserName(string userName)
{
lock (_syncRoot)
{
return _dictLoginCredentials.Values.FirstOrDefault(x => x.AccountInfo.LoginName == userName);
}
}
/// <summary>
/// 校验指定令牌的凭据是否有效。
/// </summary>
/// <param name="token"></param>
/// <returns></returns>
public bool ValidateCredential(string token)
{
lock (_syncRoot)
{
if (_dictLoginCredentials.TryGetValue(token, out var cred))
{
return cred.State == CredentialState.Alive;
}
return false;
}
}
#endregion
#region Static Methods
/// <summary>
/// 创建一个令牌。
/// </summary>
/// <returns></returns>
public static string GenerateToken()
{
return Guid.NewGuid().ToString("N");
}
#endregion
}