[Common]
移除EV.PostLoginBySameUser方法,改为UI端轮训LoginRequest状态凭据。 优化CredentialManager对于Requesting凭据字典的处理,在OnTimer方法中检测KeepAlive时移除RequestCanceled和Rejected状态的凭据。
This commit is contained in:
parent
6957751858
commit
ed26bf6bd1
|
@ -2,7 +2,6 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Aitex.Core.RT.DBCore;
|
||||
using Aitex.Core.RT.Event;
|
||||
using Aitex.Core.Util;
|
||||
|
||||
namespace Aitex.Core.Account;
|
||||
|
@ -113,10 +112,7 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
{
|
||||
var cred = kvp.Value;
|
||||
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > LOGIN_CRED_KEEP_ALIVE_TIMEOUT_SEC)
|
||||
{
|
||||
loginRemovableList.Add(cred.Token);
|
||||
EV.PostLoginBySameUser(cred.Token, new Credential());
|
||||
}
|
||||
}
|
||||
|
||||
if (loginRemovableList.Count > 0)
|
||||
|
@ -138,13 +134,30 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
var cred = kvp.Value;
|
||||
if ((DateTime.Now - cred.LastAliveTime).TotalSeconds > REQ_LOGIN_CRED_LIFT_TIME_SEC)
|
||||
requestRemovableList.Add(kvp.Key);
|
||||
|
||||
// 移除被取消或拒绝的凭据
|
||||
if(cred.State is CredentialState.RequestCanceled or CredentialState.Reject)
|
||||
requestRemovableList.Add(kvp.Key);
|
||||
}
|
||||
|
||||
if (requestRemovableList.Count > 0)
|
||||
{
|
||||
foreach (var loginName in requestRemovableList)
|
||||
{
|
||||
WriteHistory(_dictCredentialsRequesting[loginName], "REQ EXPIRED");
|
||||
var reason = "";
|
||||
switch (_dictCredentialsRequesting[loginName].State)
|
||||
{
|
||||
case CredentialState.RequestCanceled:
|
||||
reason = "REQ CANCELED";
|
||||
break;
|
||||
case CredentialState.Reject:
|
||||
reason = "REQ REJECTED";
|
||||
break;
|
||||
default:
|
||||
reason = "REQ EXPIRED";
|
||||
break;
|
||||
}
|
||||
WriteHistory(_dictCredentialsRequesting[loginName], reason);
|
||||
_dictCredentialsRequesting.Remove(loginName);
|
||||
}
|
||||
}
|
||||
|
@ -197,7 +210,7 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
/// <summary>
|
||||
/// 报告客户端处于活动状态。
|
||||
/// </summary>
|
||||
/// <param name="cred">客户端登录凭据</param>
|
||||
/// <param name="myToken">客户端登录凭据</param>
|
||||
/// <returns></returns>
|
||||
public CredentialKeepAliveResults KeepAlive(Guid myToken)
|
||||
{
|
||||
|
@ -209,9 +222,13 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
|
||||
// 如果当前用户名在请求登录列表中,则返回CredentialKeepAliveResults.RequestingLogin,通知
|
||||
// 已登录的客户端,当前用户正在请求异地登录。
|
||||
return _dictCredentialsRequesting.ContainsKey(loginCred.AccountInfo.LoginName)
|
||||
? CredentialKeepAliveResults.RequestingLogin
|
||||
: CredentialKeepAliveResults.Alive;
|
||||
if (_dictCredentialsRequesting.TryGetValue(loginCred.AccountInfo.LoginName,
|
||||
out var requestingLoginCred) && requestingLoginCred.State == CredentialState.Requesting)
|
||||
{
|
||||
return CredentialKeepAliveResults.RequestingLogin;
|
||||
}
|
||||
|
||||
return CredentialKeepAliveResults.Alive;
|
||||
}
|
||||
|
||||
return CredentialKeepAliveResults.NotFound;
|
||||
|
@ -282,21 +299,6 @@ public class CredentialManager : Singleton<CredentialManager>
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 从登录请求列表中移除指定的凭据。
|
||||
/// </summary>
|
||||
/// <param name="cred"></param>
|
||||
public void RemoveRequesting(Credential cred)
|
||||
{
|
||||
lock (_syncRoot)
|
||||
{
|
||||
if(_dictCredentialsRequesting.TryGetValue(cred.AccountInfo.LoginName, out var reqCredential))
|
||||
WriteHistory(reqCredential, "REQ CANCEL");
|
||||
|
||||
_dictCredentialsRequesting.Remove(cred.AccountInfo.LoginName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取指定用户名的登录凭据。
|
||||
/// </summary>
|
||||
|
|
|
@ -25,6 +25,11 @@ public enum CredentialState
|
|||
/// </summary>
|
||||
Requesting,
|
||||
|
||||
/// <summary>
|
||||
/// 登录请求被取消。
|
||||
/// </summary>
|
||||
RequestCanceled,
|
||||
|
||||
/// <summary>
|
||||
/// 凭据有效。
|
||||
/// </summary>
|
||||
|
|
|
@ -81,14 +81,6 @@ namespace Aitex.Core.RT.Event
|
|||
}
|
||||
}
|
||||
|
||||
public static void PostLoginBySameUser(Guid token, Credential requestedCredential)
|
||||
{
|
||||
if (InnerEventManager != null)
|
||||
{
|
||||
InnerEventManager.PostLoginBySameUser(token, requestedCredential);
|
||||
}
|
||||
}
|
||||
|
||||
public static void PostSoundMessage(string message)
|
||||
{
|
||||
if (InnerEventManager != null)
|
||||
|
|
|
@ -231,17 +231,6 @@ namespace Aitex.Core.RT.Event
|
|||
return true;
|
||||
});
|
||||
|
||||
OP.Subscribe("System.Diagnosis.GenLoginBySameUserEvent", (s, args) =>
|
||||
{
|
||||
var token = (Guid)args[0];
|
||||
var cred = CredentialManager.Instance.GetCredential(token);
|
||||
if(cred != null)
|
||||
PostLoginBySameUser(cred.Token, new Credential());
|
||||
else
|
||||
EV.PostWarningLog("Diagnosis", $"The credential with token {token} does not found.");
|
||||
return true;
|
||||
});
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
@ -473,19 +462,6 @@ namespace Aitex.Core.RT.Event
|
|||
_writerToLog.WriteEvent(eventItem);
|
||||
}
|
||||
|
||||
public void PostLoginBySameUser(Guid token, Credential requestedCredential)
|
||||
{
|
||||
var eventItem = new EventItem
|
||||
{
|
||||
Type = EventType.LoginBySameUser_Notify,
|
||||
Description = token.ToString(),
|
||||
OccuringTime = DateTime.Now,
|
||||
Tag = requestedCredential
|
||||
};
|
||||
_eventQueue.Enqueue(eventItem);
|
||||
_writerToLog.WriteEvent(eventItem);
|
||||
}
|
||||
|
||||
public void PostSoundMessage(string message)
|
||||
{
|
||||
var eventItem = new EventItem
|
||||
|
|
|
@ -50,12 +50,6 @@ namespace Aitex.Core.RT.Event
|
|||
/// RT通知消息事件。
|
||||
/// </summary>
|
||||
[EnumMember]
|
||||
HostNotification = 6,
|
||||
|
||||
/// <summary>
|
||||
/// 用户异地登录通知。
|
||||
/// </summary>
|
||||
[EnumMember]
|
||||
LoginBySameUser_Notify = 7
|
||||
HostNotification = 6
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,8 +23,6 @@ namespace Aitex.Core.RT.Event
|
|||
|
||||
void PostKickoutMessage(string message);
|
||||
|
||||
void PostLoginBySameUser(Guid token, Credential requestedCredential);
|
||||
|
||||
void PostSoundMessage(string message);
|
||||
|
||||
List<EventItem> GetAlarmEvent();
|
||||
|
|
|
@ -12,6 +12,7 @@ using Aitex.Core.RT.Event;
|
|||
using Aitex.Core.RT.Log;
|
||||
using Aitex.Core.Util;
|
||||
using Aitex.Core.WCF;
|
||||
using DocumentFormat.OpenXml.Wordprocessing;
|
||||
using MECF.Framework.Common.Account.Extends;
|
||||
using MECF.Framework.Common.Equipment;
|
||||
|
||||
|
@ -122,8 +123,6 @@ namespace MECF.Framework.Common.Account
|
|||
return await Task.Run(async () =>
|
||||
{
|
||||
// 通知已登录的用户,其它客户端使用该用户名登录,是否允许登录
|
||||
EV.PostLoginBySameUser(userLoggedIn.Token, userRequesting);
|
||||
|
||||
var ct = userRequesting.LoginRequestCancellationTokenSource.Token;
|
||||
|
||||
// 等待已登录的凭据被移除(客户端注销)
|
||||
|
@ -132,27 +131,33 @@ namespace MECF.Framework.Common.Account
|
|||
|
||||
while (true)
|
||||
{
|
||||
if (userRequesting.State == CredentialState.Confirmed)
|
||||
switch (userRequesting.State)
|
||||
{
|
||||
case CredentialState.Confirmed:
|
||||
// 客户端已注销,可以放行新的凭据
|
||||
CredentialManager.Instance.Grant(userRequesting);
|
||||
EV.PostMessage(ModuleName.System.ToString(), EventEnum.UserLoggedIn,
|
||||
userLoggedIn.AccountInfo.LoginName);
|
||||
return await Task.FromResult(LoginRequestResults.Confirmed);
|
||||
}
|
||||
|
||||
case CredentialState.Reject or CredentialState.RequestCanceled:
|
||||
if(userRequesting.State == CredentialState.Reject)
|
||||
{
|
||||
// 已登录用户拒绝了登录请求
|
||||
EV.PostInfoLog(ModuleName.System.ToString(),
|
||||
$"User {userRequesting.AccountInfo.LoginName}'s login request from {userRequesting.LoginIP}:{userRequesting.LoginPort} is rejected");
|
||||
|
||||
CredentialManager.Instance.RemoveRequesting(userRequesting);
|
||||
return await Task.FromResult(LoginRequestResults.Rejected);
|
||||
|
||||
case CredentialState.Requesting:
|
||||
case CredentialState.Alive:
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
Thread.Sleep(1000);
|
||||
ct.ThrowIfCancellationRequested();
|
||||
|
||||
Thread.Sleep(200);
|
||||
if (ct.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
// 等待指定的时间,然后向申请端发送超时
|
||||
if (sw.Elapsed.TotalSeconds > 40)
|
||||
|
@ -279,6 +284,7 @@ namespace MECF.Framework.Common.Account
|
|||
if (cred != null)
|
||||
{
|
||||
cred.LoginRequestCancellationTokenSource.Cancel();
|
||||
cred.State = CredentialState.RequestCanceled;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,8 +10,7 @@
|
|||
Title="Login Request"
|
||||
ResizeMode="CanResize"
|
||||
WindowStyle="None"
|
||||
WindowStartupLocation="CenterScreen"
|
||||
Closing="LoginRequestWaitDialog_OnClosing">
|
||||
WindowStartupLocation="CenterScreen">
|
||||
<WindowChrome.WindowChrome>
|
||||
<WindowChrome ResizeBorderThickness="0" CaptionHeight="0"/>
|
||||
</WindowChrome.WindowChrome>
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
using Aitex.Core.Account;
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
|
@ -27,10 +26,12 @@ namespace MECF.Framework.UI.Client.ClientBase.Dialog
|
|||
|
||||
_progCountDown = new Progress<double>(countDown =>
|
||||
{
|
||||
// 更新Cancel按钮倒计时数值
|
||||
// 如果倒计时为0,则关闭当前窗口
|
||||
if (countDown > 0)
|
||||
BtnCancel.Content = $"Cancel ({countDown:F0}s)";
|
||||
else
|
||||
DialogResult = false;
|
||||
DialogResult = false; // canceled
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -39,6 +40,7 @@ namespace MECF.Framework.UI.Client.ClientBase.Dialog
|
|||
base.OnSourceInitialized(e);
|
||||
|
||||
var closeTime = DateTime.Now.Add(TimeSpan.FromSeconds(CredentialManager.REQ_LOGIN_DIALOG_LIFT_TIME__SEC));
|
||||
var ct = _ctsCountDownTask?.Token;
|
||||
Task.Run(() =>
|
||||
{
|
||||
while (true)
|
||||
|
@ -46,15 +48,17 @@ namespace MECF.Framework.UI.Client.ClientBase.Dialog
|
|||
var timeRemained = (closeTime - DateTime.Now).TotalSeconds;
|
||||
if (timeRemained <= 0)
|
||||
{
|
||||
// force to reject
|
||||
// force to cancel
|
||||
_progCountDown.Report(0);
|
||||
break;
|
||||
}
|
||||
|
||||
_progCountDown.Report(timeRemained);
|
||||
|
||||
Thread.Sleep(500);
|
||||
|
||||
if (_ctsCountDownTask.Token.IsCancellationRequested)
|
||||
// 操作被取消
|
||||
if (ct is { IsCancellationRequested: true })
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
@ -62,8 +66,7 @@ namespace MECF.Framework.UI.Client.ClientBase.Dialog
|
|||
|
||||
private void BtnCancel_OnClick(object sender, RoutedEventArgs e)
|
||||
{
|
||||
_ctsCountDownTask.Cancel();
|
||||
DialogResult = false;
|
||||
Cancel();
|
||||
}
|
||||
|
||||
public void Accepted()
|
||||
|
@ -72,7 +75,7 @@ namespace MECF.Framework.UI.Client.ClientBase.Dialog
|
|||
DialogResult = true;
|
||||
}
|
||||
|
||||
private void LoginRequestWaitDialog_OnClosing(object sender, CancelEventArgs e)
|
||||
public void Cancel()
|
||||
{
|
||||
_ctsCountDownTask.Cancel();
|
||||
DialogResult = false;
|
||||
|
|
|
@ -124,33 +124,6 @@ namespace UserLoginTester
|
|||
case EventType.KickOut_Notify:
|
||||
break;
|
||||
|
||||
case EventType.LoginBySameUser_Notify:
|
||||
if (Guid.TryParse(evt.Description, out var token) && evt.Tag is Credential requestingCred)
|
||||
{
|
||||
if (_loginCred != null && token == _loginCred.Token)
|
||||
{
|
||||
Console.WriteLine(
|
||||
@"Some users is requesting to login the system, you will be forced to switch to read-only mode, do you agree?");
|
||||
|
||||
__prompt:
|
||||
Console.Write("[Y]es/[N]o: ");
|
||||
var ack = Console.ReadLine();
|
||||
switch (ack)
|
||||
{
|
||||
case "Y":
|
||||
AccountClient.Instance.Service.ConfirmLoginRequest(requestingCred.AccountInfo.LoginName);
|
||||
AccountClient.Instance.Service.LogoutEx(_loginCred.Token);
|
||||
break;
|
||||
case "N":
|
||||
AccountClient.Instance.Service.RejectLoginRequest(requestingCred.AccountInfo.LoginName);
|
||||
break;
|
||||
default:
|
||||
goto __prompt;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EventType.Sound_Notify:
|
||||
break;
|
||||
case EventType.UIMessage_Notify:
|
||||
|
|
Loading…
Reference in New Issue