123
This commit is contained in:
@@ -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)
|
||||||
|
{
|
||||||
|
_shellStream = _client.CreateShellStream("xterm", columns, rows, width, height, 1024);
|
||||||
|
_reader = new StreamReader(_shellStream);
|
||||||
|
_writer = new StreamWriter(_shellStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 单条读取,可循环读取
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
|
||||||
public StreamReader RunCommand(string command)
|
public string ReadLine()
|
||||||
{
|
{
|
||||||
|
return _reader.ReadLine();
|
||||||
var sshCommand = client.CreateCommand(command);
|
|
||||||
var asyncExecute = sshCommand.BeginExecute();
|
|
||||||
|
|
||||||
return new StreamReader(sshCommand.OutputStream);
|
|
||||||
//string outStr;
|
|
||||||
//while ((outStr = reader.ReadLine()) != null)
|
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string ServerVersion()
|
/// <summary>
|
||||||
|
/// 写入命令
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
|
||||||
|
public void WriteLine(string line)
|
||||||
{
|
{
|
||||||
return client.ConnectionInfo.ServerVersion;
|
_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(); }
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 = "";
|
||||||
|
|||||||
@@ -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)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,30 +77,38 @@
|
|||||||
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) => {
|
||||||
|
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// 监听后端终端关闭
|
// 监听后端终端关闭
|
||||||
connection.on('WriteErrorAsync', () => {
|
connection.on('WriteErrorAsync', () => {
|
||||||
|
|
||||||
@@ -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');
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user