using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.ServiceModel; using System.ServiceModel.Channels; using System.Threading; using System.Threading.Tasks; using Aitex.Common.Util; using Aitex.Core.Account; using Aitex.Core.RT.Event; using Aitex.Core.RT.Log; using Aitex.Core.Util; using Aitex.Core.WCF; using MECF.Framework.Common.Account.Extends; using MECF.Framework.Common.Equipment; namespace MECF.Framework.Common.Account { public class AccountExManager : Singleton { #region Variables private readonly Dictionary _dicLoginNameToLoginResult = new(); private readonly Dictionary _dicTokenToLoginResult = new(); private readonly string _scAccountTemplateFile = PathManager.GetCfgDir() + "Account//Account.xml"; private readonly string _scAccountLocalFile = PathManager.GetCfgDir() + "Account//_AccountEx.xml"; // 旧的_Account.xml文件路径,为兼容已有的账户配置。 private readonly string _oldAccountXmlFile = PathManager.GetCfgDir() + "Account//_Account.xml"; private readonly object _syncRoot = new(); #endregion #region COnstructors public AccountExManager() { // 默认不允许多用户登录 IsSupportMultiUserLogin = false; } #endregion #region Properties /// /// 返回角色加载器。 /// public RoleLoader RoleLoader { get; private set; } /// /// 返回是否支持多用户登录RT。 /// private bool IsSupportMultiUserLogin { get; } #endregion #region Methods /// /// 初始化当前对象。 /// /// /// public void Initialize(bool enableService) { if (!File.Exists(_scAccountLocalFile)) { if (File.Exists(_oldAccountXmlFile)) { // 如果已存在_Account.xml,则从_Account.xml创建_AccountEx.xml文件。 File.Copy(_oldAccountXmlFile, _scAccountLocalFile); Thread.Sleep(10); } else if (File.Exists(_scAccountTemplateFile)) { File.Copy(_scAccountTemplateFile, _scAccountLocalFile); Thread.Sleep(10); } // 模板文件不存在 throw new ApplicationException("Can not initialize account configuration file, " + _scAccountTemplateFile); } RoleLoader = new RoleLoader(_scAccountLocalFile); RoleLoader.Load(); if (enableService) { Singleton.Instance.Initialize(new Type[1] { typeof(AccountService) }); } } private RemoteEndpointMessageProperty GetCurrentEndPoint() { var context = OperationContext.Current; var prop = context.IncomingMessageProperties; var endpoint = prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty; return endpoint; } private CancellationTokenSource cts; public async Task RequestLogin() { if (cts is { IsCancellationRequested: false }) throw new InvalidOperationException("some user is requesting login, try again later."); cts = new CancellationTokenSource(); var token = cts.Token; return await Task.Run(async () => { await Task.Delay(5000, token); cts = null; return LoginRequestResults.Rejected; }, token); } public void CancelLoginRequest() { cts?.Cancel(); } public LoginResult AuthLogin(string loginName, string password, string role, LoginClientInfo clientInfo) { lock (_syncRoot) { var endPoint = GetCurrentEndPoint(); var loginResult = new LoginResult { ActSucc = true, Token = Guid.NewGuid().ToString(), LoginIP = endPoint.Address, LoginPort = endPoint.Port, LoginTime = DateTime.Now }; try { var accountList = RoleLoader.AccountList; var accountEx = accountList.FirstOrDefault(x => x.LoginName == loginName); if (accountEx == null) { loginResult.ActSucc = false; loginResult.Description = AuthorizeResult.NoMatchUser.ToString(); } else { var matchedAccount = accountList.FirstOrDefault(x => x.LoginName == loginName); if (matchedAccount == null) { // 登录失败,当前账户不在指定的角色中。 loginResult.ActSucc = false; loginResult.Description = AuthorizeResult.NoMatchUser.ToString(); return loginResult; } if (matchedAccount.Password != password) { // 登录失败,密码错误 loginResult.ActSucc = false; loginResult.Description = AuthorizeResult.WrongPwd.ToString(); return loginResult; } // 查找当前用户的登录角色是否存在 foreach (var roleId in matchedAccount.RoleIDs) { if (roleId == role) { // 用户名、密码、角色匹配,进入登录流程 loginResult.ActSucc = true; loginResult.AccountEx = matchedAccount; loginResult.Description = AuthorizeResult.None.ToString(); if (IsSupportMultiUserLogin) { // 如果支持多用户登录,并且相同账号异地登录,则踢掉已登录的客户端。 if (_dicLoginNameToLoginResult.TryGetValue(loginName, out var loggedInfo)) { _dicTokenToLoginResult.Remove(loggedInfo.Token); _dicLoginNameToLoginResult.Remove(loginName); EV.PostLoginBySameUser(new Credential(loggedInfo.Token, loginName)); } } else { // 如果不支持多用户登录,则踢掉所有已登录的客户端。 foreach (var user in _dicLoginNameToLoginResult) EV.PostLoginBySameUser(new Credential(user.Value.Token, user.Key)); _dicTokenToLoginResult.Clear(); _dicLoginNameToLoginResult.Clear(); } _dicLoginNameToLoginResult[loginName] = loginResult; _dicTokenToLoginResult[loginResult.Token] = loginResult; EV.PostMessage(ModuleName.System.ToString(), EventEnum.UserLoggedIn, loginResult); return loginResult; } } // 登录失败,当前账户不在指定的角色中。 loginResult.ActSucc = false; loginResult.Description = AuthorizeResult.NoMatchRole.ToString(); return loginResult; } } catch (Exception ex) { LOG.Error(ex.Message, ex); } return loginResult; } } internal void Logout(string sessionId) { lock (_syncRoot) { if (_dicTokenToLoginResult.TryGetValue(sessionId, out var loginResult)) { EV.PostMessage(ModuleName.System.ToString(), EventEnum.UserLoggedOff, _dicLoginNameToLoginResult[loginResult.AccountEx.LoginName]); _dicLoginNameToLoginResult.Remove(loginResult.AccountEx.LoginName); _dicTokenToLoginResult.Remove(sessionId); } } } #endregion } }