ssh 工具 web 实现 2023年3月14日11:25:04

master
zhangmeng 2023-03-14 11:25:33 +08:00
parent 03c300b498
commit 3a04e1c0de
13 changed files with 7707 additions and 220 deletions

View File

@ -144,6 +144,19 @@
![](./src/main/resources/static/redame/img_31.png) ![](./src/main/resources/static/redame/img_31.png)
#### 8.3 ssh 服务工具
###### 8.3.1 javafx 实现
###### 8.3.2 html 实现
> 项目借鉴开源项目 springboot + websocket 实现, [博客地址](https://blog.objectspace.cn/2020/03/10/%E4%BD%BF%E7%94%A8%E7%BA%AFJava%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AAWebSSH%E9%A1%B9%E7%9B%AE/)
> [github地址:](https://github.com/NoCortY/WebSSH)
![](./src/main/resources/static/redame/img_32.png)
## 2. 开源项目总览 ## 2. 开源项目总览
| 项目名称 |地址| | 项目名称 |地址|
@ -152,6 +165,7 @@
| rxcontrols |https://gitee.com/leewyatt/rxcontrols| | rxcontrols |https://gitee.com/leewyatt/rxcontrols|
| boot-security |https://gitee.com/zhang.w/boot-security| | boot-security |https://gitee.com/zhang.w/boot-security|
| 阿里图标库 |https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.3| | 阿里图标库 |https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.3|
| ssh工具 |https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.3|
## 3. 添加系统托盘 ## 3. 添加系统托盘

View File

@ -295,6 +295,11 @@
<version>0.1.54</version> <version>0.1.54</version>
</dependency> </dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.31</version>
</dependency>
</dependencies> </dependencies>
<build> <build>

View File

@ -4,11 +4,16 @@ import cn.hutool.core.io.BufferUtil;
import cn.hutool.core.io.FileUtil; import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IORuntimeException; import cn.hutool.core.io.IORuntimeException;
import cn.hutool.core.io.IoUtil; import cn.hutool.core.io.IoUtil;
import cn.hutool.core.lang.Dict;
import cn.hutool.core.util.CharsetUtil; import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil; import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ssh.ChannelType; import cn.hutool.extra.ssh.ChannelType;
import cn.hutool.extra.ssh.JschRuntimeException; import cn.hutool.extra.ssh.JschRuntimeException;
import cn.hutool.extra.ssh.JschUtil; import cn.hutool.extra.ssh.JschUtil;
import cn.hutool.extra.template.Template;
import cn.hutool.extra.template.TemplateConfig;
import cn.hutool.extra.template.TemplateEngine;
import cn.hutool.extra.template.TemplateUtil;
import cn.hutool.socket.aio.AioSession; import cn.hutool.socket.aio.AioSession;
import cn.hutool.socket.aio.SimpleIoAction; import cn.hutool.socket.aio.SimpleIoAction;
import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSON;
@ -23,6 +28,7 @@ import javafx.beans.value.ObservableValue;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener; import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList; import javafx.collections.ObservableList;
import javafx.concurrent.Worker;
import javafx.event.EventHandler; import javafx.event.EventHandler;
import javafx.fxml.FXML; import javafx.fxml.FXML;
import javafx.scene.control.Button; import javafx.scene.control.Button;
@ -30,7 +36,11 @@ import javafx.scene.control.TextArea;
import javafx.scene.control.TextField; import javafx.scene.control.TextField;
import javafx.scene.input.MouseButton; import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent; import javafx.scene.input.MouseEvent;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import netscape.javascript.JSObject;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.java_websocket.WebSocket; import org.java_websocket.WebSocket;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
@ -39,11 +49,11 @@ import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.handshake.ServerHandshake; import org.java_websocket.handshake.ServerHandshake;
import org.java_websocket.server.WebSocketServer; import org.java_websocket.server.WebSocketServer;
import java.io.IOException; import java.io.*;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.URI; import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
@ -63,11 +73,14 @@ public class SSHConnectionController {
@FXML @FXML
public Button connection; public Button connection;
@FXML // @FXML
public TextArea show_result; // public TextArea show_result;
//
// @FXML
// public TextField command;
@FXML @FXML
public TextField command; public WebView webView;
@FXML @FXML
private TextField username; private TextField username;
@ -93,13 +106,24 @@ public class SSHConnectionController {
private boolean isConnection = false; private boolean isConnection = false;
/**
* Javascript
*/
private JSObject javascriptConnector;
/**
* Javascript
*/
private JavaConnector javaConnector = new JavaConnector();
;
@FXML @FXML
public void initialize() { public void initialize() {
username.setText("root"); // username.setText("root");
password.setText("root"); // password.setText("root");
host.setText("192.168.52.165"); // host.setText("192.168.52.165");
port.setText("22"); // port.setText("22");
message_list.addListener((ListChangeListener<String>) c -> { message_list.addListener((ListChangeListener<String>) c -> {
while (c.next()) { while (c.next()) {
@ -113,38 +137,8 @@ public class SSHConnectionController {
} }
}); });
sshService = new SSHServiceImpl(); sshService = new SSHServiceImpl();
//启动socket server //初始化
webSocketServer = new WebSocketServer(new InetSocketAddress(8888)) { sshServer_init();
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
add_msg("WebSocketServer:onOpen--------------------------------------------");
sshService.initConnection(webSocket,uuid.getValue());
}
@Override
public void onClose(WebSocket webSocket, int i, String s, boolean b) {
add_msg("WebSocketServer:onClose--------------------------------------------");
sshService.close(webSocket,uuid.getValue());
}
@Override
public void onMessage(WebSocket webSocket, String s) {
add_msg("WebSocketServer:onMessage---" + s);
sshService.recvHandle(s,webSocket,uuid.getValue());
}
@Override
public void onError(WebSocket webSocket, Exception e) {
add_msg("WebSocketServer:onError--------------------------------------------");
}
@Override
public void onStart() {
add_msg("WebSocketServer:onStart--------------------------------------------");
}
};
connection.setOnAction(event -> { connection.setOnAction(event -> {
if (username.getText().length() == 0) { if (username.getText().length() == 0) {
AlertUtils.alert_warning("用户名不能为空!"); AlertUtils.alert_warning("用户名不能为空!");
@ -165,45 +159,124 @@ public class SSHConnectionController {
AlertUtils.alert_warning("服务端口不能为空!"); AlertUtils.alert_warning("服务端口不能为空!");
return; return;
} }
webSocketServer.start();
getConnection(); if (isConnection) {
try { try {
Thread.sleep(1000); webSocketServer.stop();
} catch (InterruptedException e) { Thread.sleep(100);
e.printStackTrace(); isConnection = false;
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
} }
sshServer_init();
webSocketServer.start();
// getConnection();
// try {
// Thread.sleep(1000);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//发送连接信息 //发送连接信息
SSHData ssh_data = create_ssh_data(command.getText(), SSHData.Type.connect); // SSHData ssh_data = create_ssh_data(command.getText(), SSHData.Type.connect);
webSocketClient.send(toString(ssh_data)); // webSocketClient.send(toString(ssh_data));
isConnection = true; isConnection = true;
//加载页面客户端
load_page_client();
status.set(1); status.set(1);
}); });
command.textProperty().addListener((observable, oldValue, newValue) -> { // command.textProperty().addListener((observable, oldValue, newValue) -> {
if (newValue != null){ // if (newValue != null){
char[] chars = newValue.toCharArray(); // char[] chars = newValue.toCharArray();
char num = 0; // char num = 0;
for (int i = 0; i < chars.length; i++) { // for (int i = 0; i < chars.length; i++) {
if (i == chars.length -1 ){ // if (i == chars.length -1 ){
num = chars[i]; // num = chars[i];
} // }
} // }
SSHData ssh_data = create_ssh_data(String.valueOf(num), SSHData.Type.command); // SSHData ssh_data = create_ssh_data(String.valueOf(num), SSHData.Type.command);
webSocketClient.send(toString(ssh_data)); // webSocketClient.send(toString(ssh_data));
// }
//
// });
// command.setOnAction(event -> {
// SSHData ssh_data = create_ssh_data("\r", SSHData.Type.command);
// webSocketClient.send(toString(ssh_data));
// command.setText(null);
// });
}
public void sshServer_init(){
//启动socket server
webSocketServer = new WebSocketServer(new InetSocketAddress(8888)) {
@Override
public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
add_msg("WebSocketServer:onOpen--------------------------------------------");
sshService.initConnection(webSocket, uuid.getValue());
} }
}); @Override
command.setOnAction(event -> { public void onClose(WebSocket webSocket, int i, String s, boolean b) {
SSHData ssh_data = create_ssh_data("\r", SSHData.Type.command); add_msg("WebSocketServer:onClose--------------------------------------------");
webSocketClient.send(toString(ssh_data)); sshService.close(webSocket, uuid.getValue());
command.setText(null); }
});
@Override
public void onMessage(WebSocket webSocket, String s) {
add_msg("WebSocketServer:onMessage---" + s);
sshService.recvHandle(s, webSocket, uuid.getValue());
}
@Override
public void onError(WebSocket webSocket, Exception e) {
add_msg("WebSocketServer:onError--------------------------------------------");
}
@Override
public void onStart() {
add_msg("WebSocketServer:onStart--------------------------------------------");
}
};
} }
private String toString(SSHData sshData){ public class JavaConnector {
return JSON.toJSONString(sshData);
public void ssh_info() {
SSHData ssh_data = create_ssh_data("", SSHData.Type.connect);
javascriptConnector.call(JSON.toJSONString(ssh_data));
}
} }
public SSHData create_ssh_data(String command,SSHData.Type type ){ public void load_page_client() {
WebEngine webEngine = webView.getEngine();
TemplateEngine engine = TemplateUtil.createEngine(new TemplateConfig("templates", TemplateConfig.ResourceMode.CLASSPATH));
Template template = engine.getTemplate("index.ftl");
Dict dict = Dict.create();
dict.set("username", username.getText());
dict.set("password", password.getText());
dict.set("host", host.getText());
dict.set("port", port.getText());
String result = template.render(dict);
URI url = null;
try {
url = this.getClass().getClassLoader().getResource("templates/ssh.html").toURI();
} catch (URISyntaxException e) {
e.printStackTrace();
}
FileUtil.writeBytes(result.getBytes(StandardCharsets.UTF_8), url.getPath());
webEngine.load(url.toASCIIString());
}
private String toString(SSHData sshData) {
return JSON.toJSONString(sshData);
}
public SSHData create_ssh_data(String command, SSHData.Type type) {
SSHData sshData = new SSHData(); SSHData sshData = new SSHData();
sshData.setUsername(username.getText()); sshData.setUsername(username.getText());
sshData.setPassword(password.getText()); sshData.setPassword(password.getText());
@ -214,34 +287,36 @@ public class SSHConnectionController {
return sshData; return sshData;
} }
private void getConnection(){ private void getConnection() {
if (webSocketClient == null) { if (webSocketClient == null) {
webSocketClient( "localhost", 8888); webSocketClient("localhost", 8888);
} }
} }
public void webSocketClient( String socket_address, int socket_port) { public void webSocketClient(String socket_address, int socket_port) {
try { try {
webSocketClient = new WebSocketClient(new URI( "ws://" + socket_address + ":" + socket_port), new Draft_6455()) { webSocketClient = new WebSocketClient(new URI("ws://" + socket_address + ":" + socket_port), new Draft_6455()) {
//连接服务端时触发 //连接服务端时触发
@Override @Override
public void onOpen(ServerHandshake handshakedata) { public void onOpen(ServerHandshake handshakedata) {
add_msg("websocket客户端和服务器连接成功!"); add_msg("websocket客户端和服务器连接成功!");
} }
//收到服务端消息时触发 //收到服务端消息时触发
@Override @Override
public void onMessage(String message) { public void onMessage(String message) {
String[] s = message.split(" "); String[] s = message.split(" ");
for (String s1 : s) { for (String s1 : s) {
add_msg( s1 ); add_msg(s1);
} }
} }
//和服务端断开连接时触发 //和服务端断开连接时触发
@Override @Override
public void onClose(int code, String reason, boolean remote) { public void onClose(int code, String reason, boolean remote) {
add_msg("websocket客户端退出连接"); add_msg("websocket客户端退出连接");
} }
//连接异常时触发 //连接异常时触发
@Override @Override
public void onError(Exception ex) { public void onError(Exception ex) {
@ -255,14 +330,15 @@ public class SSHConnectionController {
} }
public static void add_msg(String msg) { public static void add_msg(String msg) {
message_list.add(msg); // message_list.add(msg);
message_list.add("------------------------------------------------------------------->"); // message_list.add("------------------------------------------------------------------->");
message_list.add(System.lineSeparator()); // message_list.add(System.lineSeparator());
} }
public void receive(String msg) { public void receive(String msg) {
Platform.runLater(() -> { Platform.runLater(() -> {
this.show_result.setText(msg); // this.show_result.setText(msg);
}); });
} }
} }

View File

@ -20,6 +20,7 @@ import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.HBox; import javafx.scene.layout.HBox;
import javafx.scene.paint.Paint; import javafx.scene.paint.Paint;
import javafx.scene.text.Font; import javafx.scene.text.Font;
import javafx.scene.web.WebView;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.util.Callback; import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -284,6 +285,12 @@ public class ServerToolsController {
root = ftpServer; root = ftpServer;
} }
common_method(); common_method();
WebView webView = (WebView) root.lookup("#ssh_web");
AnchorPane.setTopAnchor(webView,167.0);
AnchorPane.setBottomAnchor(webView,37.0);
AnchorPane.setLeftAnchor(webView,73.0);
AnchorPane.setRightAnchor(webView,45.0);
} }
private void ftpServer(boolean flag) { private void ftpServer(boolean flag) {

View File

@ -1,135 +0,0 @@
server:
port: 8083
# max-http-header-size: 1000MB
spring:
main:
allow-bean-definition-overriding: true
autoconfigure:
exclude: com.alibaba.druid.spring.boot.autoconfigure.DruidDataSourceAutoConfigure
session:
timeout: 120m
datasource:
druid:
stat-view-servlet:
loginUsername:
loginPassword:
dynamic:
druid:
initial-size: 5
min-idle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT 1
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
poolPreparedStatements: true
maxPoolPreparedStatementPerConnectionSize: 20
filters: stat,wall,slf4j
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=5000
primary: master
strict: false
datasource:
# ? ? ? ?
master:
driver-class-name: com.mysql.cj.jdbc.Driver
type: com.alibaba.druid.pool.DruidDataSource
url: jdbc:mysql://127.0.0.1:3306/mystyle-blog?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&nullCatalogMeansCurrent=true
username: root
password: root
jpa:
database: mysql
hibernate:
ddl-auto: update
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.MySQL5Dialect
quartz:
properties:
org:
quartz:
scheduler:
instanceName: DefaultQuartzScheduler
instanceId: AUTO
jobStore:
class: org.quartz.impl.jdbcjobstore.JobStoreTX
driverDelegateClass: org.quartz.impl.jdbcjobstore.StdJDBCDelegate
tablePrefix: QRTZ_
isClustered: false
clusterCheckinInterval: 10000
useProperties: false
threadPool:
class: org.quartz.simpl.SimpleThreadPool
threadCount: 10
threadPriority: 5
threadsInheritContextClassLoaderOfInitializingThread: true
job-store-type: jdbc
jdbc:
initialize-schema: never
freemarker:
suffix: .ftl
check-template-location: true
content-type: text/html
charset: UTF-8
template-loader-path: classpath:/templates/
cache: false
enabled: true
request-context-attribute: request
mail:
default-encoding: UTF-8
port: 465
username: zhang1334717033@foxmail.com
password: gymxczptynubfgih
test-connection: false
host: smtp.qq.com
protocol: smtps
properties:
mail:
smtp:
auth: true
starttls:
enable: true
required: true
rabbitmq:
host: localhost
port: 5672
username: guest
password: guest
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
servlet:
multipart:
max-file-size: 1000MB
max-request-size: 1000MB
pagehelper:
row-bounds-with-count: true
offset-as-page-num: true
page-size-zero: true
reasonable: false
support-methods-arguments: false
params: count=countSql
helper-dialect: mysql
mybatis:
type-aliases-package: com.zhangmeng.modules
configuration:
mapUnderscoreToCamelCase: true
default-enum-type-handler: org.apache.ibatis.type.EnumOrdinalTypeHandler
mapper:
style: normal
enum-as-simple-type: true
identity: MYSQL
check-example-entity-class: true
logging:
config: classpath:logback-spring.xml
log:
level:
root: info
my: info
file-path: logs/admin-server.log
max-size: 30MB

View File

@ -2,9 +2,9 @@
<?import javafx.scene.control.Button?> <?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?> <?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.control.TextField?> <?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?> <?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.web.WebView?>
<AnchorPane prefHeight="649.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zhangmeng.tools.controller.SSHConnectionController"> <AnchorPane prefHeight="649.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zhangmeng.tools.controller.SSHConnectionController">
<children> <children>
@ -14,12 +14,13 @@
<TextField fx:id="username" layoutX="144.0" layoutY="75.0" prefHeight="25.0" prefWidth="316.0" /> <TextField fx:id="username" layoutX="144.0" layoutY="75.0" prefHeight="25.0" prefWidth="316.0" />
<TextField fx:id="host" layoutX="144.0" layoutY="127.0" prefHeight="25.0" prefWidth="316.0" /> <TextField fx:id="host" layoutX="144.0" layoutY="127.0" prefHeight="25.0" prefWidth="316.0" />
<TextField fx:id="password" layoutX="553.0" layoutY="75.0" prefHeight="25.0" prefWidth="316.0" /> <TextField fx:id="password" layoutX="553.0" layoutY="75.0" prefHeight="25.0" prefWidth="316.0" />
<TextArea fx:id="show_result" layoutX="144.0" layoutY="181.0" prefHeight="269.0" prefWidth="997.0" AnchorPane.bottomAnchor="199.0" AnchorPane.leftAnchor="144.0" AnchorPane.rightAnchor="59.0" AnchorPane.topAnchor="181.0" /> <!-- <TextArea fx:id="show_result" layoutX="144.0" layoutY="181.0" prefHeight="269.0" prefWidth="997.0" AnchorPane.bottomAnchor="199.0" AnchorPane.leftAnchor="144.0" AnchorPane.rightAnchor="59.0" AnchorPane.topAnchor="181.0" />-->
<Label layoutX="86.0" layoutY="181.0" text="显示:" AnchorPane.bottomAnchor="451.0" /> <!-- <Label layoutX="86.0" layoutY="181.0" text="显示:" AnchorPane.bottomAnchor="451.0" />-->
<Label layoutX="507.0" layoutY="131.0" text="端口:" /> <Label layoutX="507.0" layoutY="131.0" text="端口:" />
<TextField fx:id="port" layoutX="553.0" layoutY="127.0" prefHeight="25.0" prefWidth="316.0" /> <TextField fx:id="port" layoutX="553.0" layoutY="127.0" prefHeight="25.0" prefWidth="316.0" />
<Button fx:id="connection" layoutX="919.0" layoutY="127.0" mnemonicParsing="false" text="连接" /> <Button fx:id="connection" layoutX="919.0" layoutY="127.0" mnemonicParsing="false" text="连接" />
<Label layoutX="84.0" layoutY="487.0" text="命令:" AnchorPane.bottomAnchor="145.0" /> <WebView id="ssh_web" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" fx:id="webView" layoutX="73.0" layoutY="167.0" prefHeight="445.0" prefWidth="1082.0" AnchorPane.bottomAnchor="37.0" AnchorPane.leftAnchor="73.0" AnchorPane.rightAnchor="45.0" AnchorPane.topAnchor="167.0" />
<TextField fx:id="command" layoutX="144.0" layoutY="483.0" prefHeight="25.0" prefWidth="997.0" AnchorPane.bottomAnchor="141.0" AnchorPane.leftAnchor="144.0" AnchorPane.rightAnchor="59.0" /> <!-- <Label layoutX="84.0" layoutY="487.0" text="命令:" AnchorPane.bottomAnchor="145.0" />-->
<!-- <TextField fx:id="command" layoutX="144.0" layoutY="483.0" prefHeight="25.0" prefWidth="997.0" AnchorPane.bottomAnchor="141.0" AnchorPane.leftAnchor="144.0" AnchorPane.rightAnchor="59.0" />-->
</children> </children>
</AnchorPane> </AnchorPane>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,56 @@
function WSSHClient() {
};
WSSHClient.prototype._generateEndpoint = function () {
if (window.location.protocol == 'https:') {
var protocol = 'wss://';
} else {
var protocol = 'ws://';
}
var endpoint = protocol+'127.0.0.1:8888';
return endpoint;
};
WSSHClient.prototype.connect = function (options) {
var endpoint = this._generateEndpoint();
if (window.WebSocket) {
//如果支持websocket
this._connection = new WebSocket(endpoint);
}else {
//否则报错
options.onError('WebSocket Not Supported');
return;
}
this._connection.onopen = function () {
options.onConnect();
};
this._connection.onmessage = function (evt) {
var data = evt.data.toString();
//data = base64.decode(data);
options.onData(data);
};
this._connection.onclose = function (evt) {
options.onClose();
};
};
WSSHClient.prototype.send = function (data) {
this._connection.send(JSON.stringify(data));
};
WSSHClient.prototype.sendInitData = function (options) {
//连接参数
this._connection.send(JSON.stringify(options));
}
WSSHClient.prototype.sendClientData = function (data) {
//发送指令
this._connection.send(JSON.stringify({"operate": "command", "command": data}))
}
var client = new WSSHClient();

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 98 KiB

View File

@ -0,0 +1,68 @@
<!doctype html>
<html>
<head>
<title>WebSSH</title>
<link rel="stylesheet" href="../static/css/xterm.css" />
</head>
<body>
<div id="terminal" style="width: 100%;height: 100%"></div>
<script src="../static/js/jquery-3.4.1.min.js"></script>
<script src="../static/js/xterm.js" charset="utf-8"></script>
<script src="../static/js/webssh.js" charset="utf-8"></script>
<script>
var host = '${host}';
var port = '${port}';
var username = '${username}';
var password = '${password}';
openTerminal( {
operate:'connect',
host: host,//IP
port: port,//端口号
username: username,//用户名
password: password//密码
});
function openTerminal(options){
var client = new WSSHClient();
var term = new Terminal({
cols: 97,
rows: 37,
cursorBlink: true, // 光标闪烁
cursorStyle: "block", // 光标样式 null | 'block' | 'underline' | 'bar'
scrollback: 800, //回滚
tabStopWidth: 8, //制表宽度
screenKeys: true
});
term.on('data', function (data) {
//键盘输入时的回调函数
client.sendClientData(data);
});
term.open(document.getElementById('terminal'));
//在页面上显示连接中...
term.write('Connecting...');
//执行连接操作
client.connect({
onError: function (error) {
//连接失败回调
term.write('Error: ' + error + '\r\n');
},
onConnect: function () {
//连接成功回调
client.sendInitData(options);
},
onClose: function () {
//连接关闭回调
term.write("\rconnection closed");
},
onData: function (data) {
//收到数据时回调
term.write(data);
}
});
}
</script>
</body>
</html>

View File