This commit is contained in:
Mn
2023-11-16 18:25:38 +08:00
parent f12a0ff25c
commit 8382129a49
4 changed files with 270 additions and 64 deletions

View File

@@ -16,47 +16,109 @@ namespace NetPanel.Bl
private string _pwd = ""; private string _pwd = "";
private string _host = ""; private string _host = "";
private SshClient client = null; /// <summary>
/// 客户端
/// </summary>
private SshClient _client = null;
/// <summary>
/// sell
/// </summary>
private ShellStream _shellStream = null;
/// <summary>
/// 读取流
/// </summary>
private StreamReader _reader = null;
/// <summary>
/// 写入流
/// </summary>
private StreamWriter _writer = null;
public SshBl(string host, string username, string pwd) /// <summary>
/// 是否连接完成
/// </summary>
private bool _isConnected = false;
/// <summary>
/// ssh连接
/// </summary>
/// <param name="host">ip</param>
/// <param name="username">登录用户</param>
/// <param name="pwd">登录密码</param>
/// <param name="columns">单元格</param>
/// <param name="rows">行</param>
/// <param name="width">宽</param>
/// <param name="height">高</param>
public SshBl(string host, string username, string pwd, uint columns, uint rows, uint width, uint height)
{ {
_username = username; _username = username;
_pwd = pwd; _pwd = pwd;
_host = host; _host = host;
client = new SshClient(host, username, pwd); _client = new SshClient(host, username, pwd);
client.Connect(); _client.Connect();
} if (_client.IsConnected)
public StreamReader RunCommand(string command)
{ {
_shellStream = _client.CreateShellStream("xterm", columns, rows, width, height, 1024);
var sshCommand = client.CreateCommand(command); _reader = new StreamReader(_shellStream);
var asyncExecute = sshCommand.BeginExecute(); _writer = new StreamWriter(_shellStream);
}
return new StreamReader(sshCommand.OutputStream);
//string outStr;
//while ((outStr = reader.ReadLine()) != null)
//{
//}
} }
public string ServerVersion()
/// <summary>
/// 单条读取,可循环读取
/// </summary>
/// <returns></returns>
public string ReadLine()
{ {
return client.ConnectionInfo.ServerVersion; return _reader.ReadLine();
} }
/// <summary>
/// 写入命令
/// </summary>
/// <returns></returns>
public void WriteLine(string line)
{
_writer.WriteLine(line);
}
/// <summary>
/// 全部读取,可循环读取
/// </summary>
/// <returns></returns>
public string ReadToEnd()
{
return _reader.ReadToEnd();
}
/// <summary>
/// Ssh 客户端
/// </summary>
public SshClient Client { get { return _client; } }
/// <summary> /// <summary>
/// 关闭 /// 关闭
/// </summary> /// </summary>
public void Dispose() public void Dispose()
{ {
client.Disconnect();
client.Dispose(); if (_writer != null) _writer.Close();
if (_reader != null) _reader.Close();
//if (_shellStream != null) _shellStream.Close();
if (_shellStream != null) _shellStream.Dispose();
if (_client != null) { _client.Disconnect(); _client.Dispose(); }
} }
} }
} }

View File

@@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using NetPanel.Bl; using NetPanel.Bl;
using NetPanel.Help;
using Renci.SshNet;
using System.Diagnostics;
using System.Text; using System.Text;
namespace NetPanel.Controllers.SSH namespace NetPanel.Controllers.SSH
@@ -13,10 +15,39 @@ namespace NetPanel.Controllers.SSH
public IActionResult SSH() public async Task<IActionResult> SSH()
{ {
//SshBl sshBl = new SshBl("172.31.110.239", "root", "123456789"); //SshBl sshBl = new SshBl("172.29.119.239", "root", "123456789", 80, 24, 800, 600);
//var output = sshBl.ReadLine();
//sshBl.WriteLine("top");
//int cc = 0;
//while (true)
//{
// var outpu3 = sshBl.Read();
// if (cc == 0)
// {
// await Task.Delay(5000);
// sshBl.WriteLine("\x03");
// cc = 1;
// }
// else if (cc == 2)
// {
// break;
// }
//}
//sshBl.Dispose();
////string tt = sshBl.ServerVersion(); ////string tt = sshBl.ServerVersion();
//StringBuilder sbStr = new StringBuilder(); //StringBuilder sbStr = new StringBuilder();
//string tt = ""; //string tt = "";

View File

@@ -1,7 +1,13 @@
using Microsoft.AspNetCore.SignalR; using Microsoft.AspNetCore.SignalR;
using NetPanel.Bl; using NetPanel.Bl;
using NetPanel.Entity; using NetPanel.Entity;
using NetPanel.Help;
using Renci.SshNet.Common;
using Renci.SshNet.Messages; using Renci.SshNet.Messages;
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Net.Sockets;
using System.Security.Cryptography; using System.Security.Cryptography;
using System.Text; using System.Text;
@@ -10,6 +16,15 @@ namespace NetPanel.SignalR
public class ChatHub : Hub public class ChatHub : Hub
{ {
/// <summary>
/// ssh 管理
/// </summary>
private static Dictionary<string, SshBl> dicSsh = new Dictionary<string, SshBl>();
/// <summary>
/// 建立连接时
/// </summary>
/// <returns></returns>
public override async Task OnConnectedAsync() public override async Task OnConnectedAsync()
{ {
@@ -25,30 +40,114 @@ namespace NetPanel.SignalR
await client.SendAsync("ConnectionId", rm); await client.SendAsync("ConnectionId", rm);
} }
/// <summary>
/// 断开异步时
/// </summary>
/// <param name="exception"></param>
/// <returns></returns>
public async Task<ReturnMsg> CreateConnectionAsync(string connectionId, string command) public override async Task OnDisconnectedAsync(Exception? ex)
{
var cid = Context.ConnectionId;
if (dicSsh.ContainsKey(cid))
{
dicSsh[cid].Dispose();
dicSsh.Remove(cid);
}
await base.OnDisconnectedAsync(ex);
}
/// <summary>
/// 创建终端链接
/// </summary>
/// <param name="connectionId"></param>
/// <param name="command"></param>
/// <returns></returns>
public async Task<ReturnMsg> CreateConnectionAsync(uint width, uint height, uint columns, uint rows)
{
var cid = Context.ConnectionId;
ReturnMsg rm = new ReturnMsg();
rm.Code = 1;
if (!dicSsh.ContainsKey(cid))
{
SshBl ssh = new SshBl("172.29.119.239", "root", "123456789", columns, rows, width, height);
dicSsh.Add(cid, ssh);
ReceiveMessage(cid);
}
return rm;
}
/// <summary>
/// 写入命令
/// </summary>
/// <param name="curr_line"></param>
/// <returns></returns>
public async Task<ReturnMsg> WriteLineAsync(string curr_line)
{ {
ReturnMsg rm = new ReturnMsg(); ReturnMsg rm = new ReturnMsg();
rm.Code = 1; rm.Code = 1;
var cid = Context.ConnectionId;
//SshBl sshBl = new SshBl("172.31.110.239", "root", "123456789"); if (dicSsh.ContainsKey(cid))
////string tt = sshBl.ServerVersion(); {
//StringBuilder sbStr = new StringBuilder(); dicSsh[cid].WriteLine(curr_line);
//string tt = ""; ReceiveMessage(cid);
//var reader = sshBl.RunCommand("top"); }
//string outStr = null;
//while ((outStr = reader.ReadLine()) != null)
//{
// sbStr.Append(outStr + "/r/n");
//}
rm.Obj = "====>" + command;
//根据id获取指定客户端
var client = Clients.Client(connectionId);
// await client.SendAsync("CreateConnectionAsync", rm);
return rm; return rm;
} }
/// <summary>
/// 发送响应
/// </summary>
/// <param name="ssh"></param>
/// <returns></returns>
public async Task ReceiveMessage(string cid)
{
ReturnMsg rm = new ReturnMsg();
rm.Code = 1;
int count = 0;
SshBl ssh = dicSsh[cid];
//根据id获取指定客户端
var client = Clients.Client(cid);
while (true)
{
try
{
string line = ssh.ReadLine();
if (line.IsNotNull())
{
if (line.Contains(":~#"))
{
rm.Code = 2; ;
rm.Obj = line;
await client.SendAsync("ReceiveMessage", rm);
break;
}
else
{
rm.Obj = line + "\n";
await client.SendAsync("ReceiveMessage", rm);
}
}
else
{
await Task.Delay(100);
}
}
catch (Exception ex)
{
}
}
}
} }
} }

View File

@@ -49,8 +49,8 @@
convertEol: true, //启用时,光标将设置为下一行的开头 convertEol: true, //启用时,光标将设置为下一行的开头
disableStdin: false, //是否应禁用输入。 disableStdin: false, //是否应禁用输入。
theme: { theme: {
foreground: 'yellow', //字体 // foreground: 'yellow', //字体
background: '#060101', //背景色 // background: '#060101', //背景色
cursor: 'help',//设置光标 cursor: 'help',//设置光标
} }
}); });
@@ -58,9 +58,15 @@
// 获取窗口的宽度和高度。 // 获取窗口的宽度和高度。
const width = window.innerWidth; const width = window.innerWidth;
const height = window.innerHeight; const height = window.innerHeight;
const columns = parseInt(width / 10);
const rows = parseInt(height / 22);
//cursorx 这个长度不能删除,用于ev.keyCode === 8
var cursorx = 0;
// 调整终端的尺寸。 // 调整终端的尺寸。
term.resize(parseInt(width / 10), parseInt(height / 22)); term.resize(columns, parseInt(height / 22));
//回车输入的内容 //回车输入的内容
var curr_line = ''; var curr_line = '';
@@ -71,28 +77,36 @@
var connectionId = ''; var connectionId = '';
term.open(document.getElementById('terminal')); term.open(document.getElementById('terminal'));
term.prompt = () => { term.prompt = () => {
term.write('\n\u001b[32m$ >\u001b[37m'); term.write('\n\u001b[32m$ >\u001b[37m');
}; };
//通讯 //通讯
var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build(); var connection = new signalR.HubConnectionBuilder().withUrl("/chatHub").build();
//signalR接收消息 //signalR接收消息
connection.on("ReceiveMessage", function (user, message) { connection.on("ReceiveMessage", function (msg) {
term.write(message); term.write(msg.obj);
}); });
//获取通讯id // 已建立连接
connection.on("ConnectionId", function (msg) { connection.on("ConnectionId", function (msg) {
// term.write('Welcome to my Scheme web intepreter!\r\n123');
term.write('Welcome to my Scheme web intepreter!\r\n123'); // term.prompt();
term.prompt();
connectionId = msg.obj; connectionId = msg.obj;
//创建 ssh 客户端
connection.invoke('CreateConnectionAsync', width, height, columns, rows).then((result) => {
}); });
});
// 监听后端终端关闭 // 监听后端终端关闭
@@ -104,26 +118,26 @@
term.on('key', function (key, ev) { term.on('key', function (key, ev) {
const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey const printable = !ev.altKey && !ev.altGraphKey && !ev.ctrlKey && !ev.metaKey
//const printable = !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.metaKey; //const printable = !e.domEvent.altKey && !e.domEvent.altGraphKey && !e.domEvent.ctrlKey && !e.domEvent.metaKey;
if (cursorx == 0) {
cursorx = term.buffer.cursorX;
}
if (ev.keyCode === 13) { // Enter key if (ev.keyCode === 13) { // Enter key
if (curr_line.replace(/^\s+|\s+$/g, '').length != 0) { // Check if string is all whitespace if (curr_line.replace(/^\s+|\s+$/g, '').length != 0) { // Check if string is all whitespace
entries.push(curr_line); entries.push(curr_line);
currPos = entries.length - 1; currPos = entries.length - 1;
// term.prompt(); // term.prompt();
connection.invoke('CreateConnectionAsync', connectionId, curr_line).then((result) => {
if (result.code == 1) {
//term.prompt();
//term.write(result.obj);
term.write('\n' + result.obj); connection.invoke('WriteLineAsync', curr_line).then((result) => {
term.prompt(); if (result.code == 1) {
// term.write('\n' + result.obj);
// term.prompt();
} }
}); });
@@ -133,7 +147,7 @@
} }
curr_line = ''; curr_line = '';
} else if (ev.keyCode === 8) { // Backspace } else if (ev.keyCode === 8) { // Backspace
if (term.buffer.cursorX > 3) { if (term.buffer.cursorX > cursorx) {
curr_line = curr_line.slice(0, -1); curr_line = curr_line.slice(0, -1);
term.write('\b \b'); term.write('\b \b');
} }