You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

110 lines
3.5 KiB

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using CoreAgent.ProtocolClient.Models;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json.Linq;
namespace CoreAgent.ProtocolClient.ProtocolEngineCore
{
/// <summary>
/// 管理客户端的认证过程
/// 职责:
/// 1. 处理 "authenticate" 消息响应。
/// 2. 根据服务器的 challenge 发起认证请求。
/// 3. 维护和提供认证状态 (IsAuthenticated)。
/// 4. 在认证成功后触发事件通知。
/// </summary>
public class AuthenticationManager
{
private readonly ProtocolClientConfig _config;
private readonly ILogger _logger;
private readonly Action<JObject> _sendMessage;
private bool _isAuthenticated = false;
public bool IsAuthenticated => _isAuthenticated;
public event EventHandler? Authenticated;
public AuthenticationManager(ProtocolClientConfig config, ILogger logger, Action<JObject> sendMessage)
{
_config = config;
_logger = logger;
_sendMessage = sendMessage;
}
/// <summary>
/// 处理收到的认证相关消息。
/// </summary>
public void HandleMessage(JObject message)
{
var messageType = message["message"]?.ToString();
if (messageType != "authenticate" && messageType != "ready")
{
return;
}
if (_isAuthenticated) return;
switch (messageType)
{
case "authenticate":
if (message["ready"]?.Value<bool>() == true)
{
OnAuthenticationSuccess();
}
else if (message["error"] == null && !string.IsNullOrEmpty(_config.Password))
{
var challenge = message["challenge"]?.ToString() ?? "";
PerformAuthentication(challenge);
}
else
{
_logger.LogError($"[{_config.Name}] 认证失败: {message["error"]}");
}
break;
case "ready":
_logger.LogInformation($"[{_config.Name}] 直接收到ready消息,视为认证成功");
OnAuthenticationSuccess();
break;
}
}
/// <summary>
/// 当收到 "ready" 消息或认证成功时调用,标记为已认证并触发事件。
/// </summary>
public void HandleReadyMessage()
{
if (!_isAuthenticated)
{
_logger.LogInformation($"[{_config.Name}] 收到 ready 消息,完成认证");
OnAuthenticationSuccess();
}
}
private void PerformAuthentication(string challenge)
{
var authMessage = new JObject
{
["message"] = "authenticate",
["password"] = _config.Password,
["challenge"] = challenge
};
_sendMessage(authMessage);
}
private void OnAuthenticationSuccess()
{
_logger.LogInformation($"[{_config.Name}] 认证成功");
_isAuthenticated = true;
Authenticated?.Invoke(this, EventArgs.Empty);
}
public void Reset()
{
_isAuthenticated = false;
}
}
}