249 lines
8.1 KiB
C#

using AmtScanner.Api.Data;
using AmtScanner.Api.Models;
using AmtScanner.Api.Services;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace AmtScanner.Api.Controllers;
/// <summary>
/// 远程桌面控制器
/// </summary>
[ApiController]
[Route("api/remote-desktop")]
public class RemoteDesktopController : ControllerBase
{
private readonly ILogger<RemoteDesktopController> _logger;
private readonly GuacamoleService _guacamoleService;
private readonly AppDbContext _db;
private readonly IConfiguration _config;
public RemoteDesktopController(
ILogger<RemoteDesktopController> logger,
GuacamoleService guacamoleService,
AppDbContext db,
IConfiguration config)
{
_logger = logger;
_guacamoleService = guacamoleService;
_db = db;
_config = config;
}
/// <summary>
/// 连接到设备的远程桌面 (RDP)
/// </summary>
[HttpPost("connect/rdp")]
public async Task<IActionResult> ConnectRdp([FromBody] RdpConnectRequest request)
{
if (string.IsNullOrEmpty(request.Hostname))
{
return BadRequest(ApiResponse.Fail(400, "主机地址不能为空"));
}
try
{
var connectionName = $"RDP-{request.Hostname}-{DateTime.Now:yyyyMMddHHmmss}";
var connectionId = await _guacamoleService.CreateRdpConnectionAsync(
connectionName,
request.Hostname,
request.Username ?? "",
request.Password ?? "",
request.Port);
if (string.IsNullOrEmpty(connectionId))
{
return BadRequest(ApiResponse.Fail(500, "创建远程连接失败,请检查 Guacamole 服务是否正常"));
}
var connectionUrl = await _guacamoleService.GetConnectionUrlAsync(connectionId);
return Ok(ApiResponse.Success(new
{
connectionId,
connectionUrl,
guacamoleUrl = _config["Guacamole:BaseUrl"] ?? "http://localhost:8080/guacamole"
}));
}
catch (Exception ex)
{
_logger.LogError(ex, "创建 RDP 连接失败");
return BadRequest(ApiResponse.Fail(500, $"创建连接失败: {ex.Message}"));
}
}
/// <summary>
/// 连接到设备的远程桌面 (VNC)
/// </summary>
[HttpPost("connect/vnc")]
public async Task<IActionResult> ConnectVnc([FromBody] VncConnectRequest request)
{
if (string.IsNullOrEmpty(request.Hostname))
{
return BadRequest(ApiResponse.Fail(400, "主机地址不能为空"));
}
try
{
var connectionName = $"VNC-{request.Hostname}-{DateTime.Now:yyyyMMddHHmmss}";
var connectionId = await _guacamoleService.CreateVncConnectionAsync(
connectionName,
request.Hostname,
request.Password ?? "",
request.Port);
if (string.IsNullOrEmpty(connectionId))
{
return BadRequest(ApiResponse.Fail(500, "创建远程连接失败,请检查 Guacamole 服务是否正常"));
}
var connectionUrl = await _guacamoleService.GetConnectionUrlAsync(connectionId);
return Ok(ApiResponse.Success(new
{
connectionId,
connectionUrl,
guacamoleUrl = _config["Guacamole:BaseUrl"] ?? "http://localhost:8080/guacamole"
}));
}
catch (Exception ex)
{
_logger.LogError(ex, "创建 VNC 连接失败");
return BadRequest(ApiResponse.Fail(500, $"创建连接失败: {ex.Message}"));
}
}
/// <summary>
/// 通过设备 UUID 连接远程桌面
/// </summary>
[HttpPost("connect/device/{uuid}")]
public async Task<IActionResult> ConnectByDevice(string uuid, [FromBody] DeviceConnectRequest request)
{
// 先查找 Agent 设备
var agentDevice = await _db.AgentDevices_new.FirstOrDefaultAsync(d => d.Uuid == uuid);
if (agentDevice != null)
{
var connectionName = $"RDP-{agentDevice.Hostname ?? agentDevice.IpAddress}-{DateTime.Now:yyyyMMddHHmmss}";
var connectionId = await _guacamoleService.CreateRdpConnectionAsync(
connectionName,
agentDevice.IpAddress,
request.Username ?? "",
request.Password ?? "",
request.Port > 0 ? request.Port : 3389);
if (string.IsNullOrEmpty(connectionId))
{
return BadRequest(ApiResponse.Fail(500, "创建远程连接失败"));
}
var connectionUrl = await _guacamoleService.GetConnectionUrlAsync(connectionId);
return Ok(ApiResponse.Success(new
{
connectionId,
connectionUrl,
deviceName = agentDevice.Hostname ?? agentDevice.IpAddress,
guacamoleUrl = _config["Guacamole:BaseUrl"] ?? "http://localhost:8080/guacamole"
}));
}
// 再查找 AMT 设备
var amtDevice = await _db.AmtDevices_new.FirstOrDefaultAsync(d => d.Uuid == uuid);
if (amtDevice != null)
{
var connectionName = $"RDP-{amtDevice.Hostname ?? amtDevice.IpAddress}-{DateTime.Now:yyyyMMddHHmmss}";
var connectionId = await _guacamoleService.CreateRdpConnectionAsync(
connectionName,
amtDevice.IpAddress,
request.Username ?? "",
request.Password ?? "",
request.Port > 0 ? request.Port : 3389);
if (string.IsNullOrEmpty(connectionId))
{
return BadRequest(ApiResponse.Fail(500, "创建远程连接失败"));
}
var connectionUrl = await _guacamoleService.GetConnectionUrlAsync(connectionId);
return Ok(ApiResponse.Success(new
{
connectionId,
connectionUrl,
deviceName = amtDevice.Hostname ?? amtDevice.IpAddress,
guacamoleUrl = _config["Guacamole:BaseUrl"] ?? "http://localhost:8080/guacamole"
}));
}
return NotFound(ApiResponse.Fail(404, "设备不存在"));
}
/// <summary>
/// 断开连接(删除 Guacamole 连接)
/// </summary>
[HttpDelete("disconnect/{connectionId}")]
public async Task<IActionResult> Disconnect(string connectionId)
{
var result = await _guacamoleService.DeleteConnectionAsync(connectionId);
if (result)
{
return Ok(ApiResponse.Success("连接已断开"));
}
else
{
return BadRequest(ApiResponse.Fail(500, "断开连接失败"));
}
}
/// <summary>
/// 获取所有远程连接
/// </summary>
[HttpGet("connections")]
public async Task<IActionResult> GetConnections()
{
var connections = await _guacamoleService.GetConnectionsAsync();
return Ok(ApiResponse.Success(connections));
}
/// <summary>
/// 获取 Guacamole 配置信息
/// </summary>
[HttpGet("config")]
public IActionResult GetConfig()
{
return Ok(ApiResponse.Success(new
{
guacamoleUrl = _config["Guacamole:BaseUrl"] ?? "http://localhost:8080/guacamole",
enabled = !string.IsNullOrEmpty(_config["Guacamole:BaseUrl"])
}));
}
}
public class RdpConnectRequest
{
public string Hostname { get; set; } = "";
public string? Username { get; set; }
public string? Password { get; set; }
public int Port { get; set; } = 3389;
}
public class VncConnectRequest
{
public string Hostname { get; set; } = "";
public string? Password { get; set; }
public int Port { get; set; } = 5900;
}
public class DeviceConnectRequest
{
public string? Username { get; set; }
public string? Password { get; set; }
public int Port { get; set; } = 3389;
public string Protocol { get; set; } = "rdp"; // rdp 或 vnc
}