ssh 工具 web 实现 2023年3月14日11:25:04
parent
03c300b498
commit
3a04e1c0de
14
README.md
14
README.md
|
|
@ -144,6 +144,19 @@
|
|||
|
||||

|
||||
|
||||
#### 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)
|
||||
|
||||

|
||||
|
||||
## 2. 开源项目总览
|
||||
|
||||
| 项目名称 |地址|
|
||||
|
|
@ -152,6 +165,7 @@
|
|||
| rxcontrols |https://gitee.com/leewyatt/rxcontrols|
|
||||
| boot-security |https://gitee.com/zhang.w/boot-security|
|
||||
| 阿里图标库 |https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.3|
|
||||
| ssh工具 |https://www.iconfont.cn/home/index?spm=a313x.7781069.1998910419.3|
|
||||
|
||||
## 3. 添加系统托盘
|
||||
|
||||
|
|
|
|||
5
pom.xml
5
pom.xml
|
|
@ -295,6 +295,11 @@
|
|||
<version>0.1.54</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.31</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
|
|
|||
|
|
@ -4,11 +4,16 @@ import cn.hutool.core.io.BufferUtil;
|
|||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.io.IORuntimeException;
|
||||
import cn.hutool.core.io.IoUtil;
|
||||
import cn.hutool.core.lang.Dict;
|
||||
import cn.hutool.core.util.CharsetUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.hutool.extra.ssh.ChannelType;
|
||||
import cn.hutool.extra.ssh.JschRuntimeException;
|
||||
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.SimpleIoAction;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
|
|
@ -23,6 +28,7 @@ import javafx.beans.value.ObservableValue;
|
|||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.concurrent.Worker;
|
||||
import javafx.event.EventHandler;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Button;
|
||||
|
|
@ -30,7 +36,11 @@ import javafx.scene.control.TextArea;
|
|||
import javafx.scene.control.TextField;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.input.MouseEvent;
|
||||
import javafx.scene.web.WebEngine;
|
||||
import javafx.scene.web.WebView;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import netscape.javascript.JSObject;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.java_websocket.WebSocket;
|
||||
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.server.WebSocketServer;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.*;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.Charset;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
|
@ -63,11 +73,14 @@ public class SSHConnectionController {
|
|||
@FXML
|
||||
public Button connection;
|
||||
|
||||
@FXML
|
||||
public TextArea show_result;
|
||||
// @FXML
|
||||
// public TextArea show_result;
|
||||
//
|
||||
// @FXML
|
||||
// public TextField command;
|
||||
|
||||
@FXML
|
||||
public TextField command;
|
||||
public WebView webView;
|
||||
|
||||
@FXML
|
||||
private TextField username;
|
||||
|
|
@ -93,13 +106,24 @@ public class SSHConnectionController {
|
|||
|
||||
private boolean isConnection = false;
|
||||
|
||||
/**
|
||||
* 用于与Javascript引擎通信。
|
||||
*/
|
||||
private JSObject javascriptConnector;
|
||||
|
||||
/**
|
||||
* 用于从Javascript引擎进行通信。
|
||||
*/
|
||||
private JavaConnector javaConnector = new JavaConnector();
|
||||
;
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
|
||||
username.setText("root");
|
||||
password.setText("root");
|
||||
host.setText("192.168.52.165");
|
||||
port.setText("22");
|
||||
// username.setText("root");
|
||||
// password.setText("root");
|
||||
// host.setText("192.168.52.165");
|
||||
// port.setText("22");
|
||||
|
||||
message_list.addListener((ListChangeListener<String>) c -> {
|
||||
while (c.next()) {
|
||||
|
|
@ -113,38 +137,8 @@ public class SSHConnectionController {
|
|||
}
|
||||
});
|
||||
sshService = new SSHServiceImpl();
|
||||
//启动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
|
||||
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--------------------------------------------");
|
||||
}
|
||||
};
|
||||
|
||||
//初始化
|
||||
sshServer_init();
|
||||
connection.setOnAction(event -> {
|
||||
if (username.getText().length() == 0) {
|
||||
AlertUtils.alert_warning("用户名不能为空!");
|
||||
|
|
@ -165,45 +159,124 @@ public class SSHConnectionController {
|
|||
AlertUtils.alert_warning("服务端口不能为空!");
|
||||
return;
|
||||
}
|
||||
webSocketServer.start();
|
||||
getConnection();
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
if (isConnection) {
|
||||
try {
|
||||
webSocketServer.stop();
|
||||
Thread.sleep(100);
|
||||
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);
|
||||
webSocketClient.send(toString(ssh_data));
|
||||
// SSHData ssh_data = create_ssh_data(command.getText(), SSHData.Type.connect);
|
||||
// webSocketClient.send(toString(ssh_data));
|
||||
|
||||
isConnection = true;
|
||||
//加载页面客户端
|
||||
load_page_client();
|
||||
status.set(1);
|
||||
});
|
||||
command.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
if (newValue != null){
|
||||
char[] chars = newValue.toCharArray();
|
||||
char num = 0;
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (i == chars.length -1 ){
|
||||
num = chars[i];
|
||||
}
|
||||
}
|
||||
SSHData ssh_data = create_ssh_data(String.valueOf(num), SSHData.Type.command);
|
||||
webSocketClient.send(toString(ssh_data));
|
||||
// command.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
// if (newValue != null){
|
||||
// char[] chars = newValue.toCharArray();
|
||||
// char num = 0;
|
||||
// for (int i = 0; i < chars.length; i++) {
|
||||
// if (i == chars.length -1 ){
|
||||
// num = chars[i];
|
||||
// }
|
||||
// }
|
||||
// SSHData ssh_data = create_ssh_data(String.valueOf(num), SSHData.Type.command);
|
||||
// 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());
|
||||
}
|
||||
|
||||
});
|
||||
command.setOnAction(event -> {
|
||||
SSHData ssh_data = create_ssh_data("\r", SSHData.Type.command);
|
||||
webSocketClient.send(toString(ssh_data));
|
||||
command.setText(null);
|
||||
});
|
||||
@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--------------------------------------------");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private String toString(SSHData sshData){
|
||||
return JSON.toJSONString(sshData);
|
||||
public class JavaConnector {
|
||||
|
||||
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.setUsername(username.getText());
|
||||
sshData.setPassword(password.getText());
|
||||
|
|
@ -214,34 +287,36 @@ public class SSHConnectionController {
|
|||
return sshData;
|
||||
}
|
||||
|
||||
private void getConnection(){
|
||||
private void getConnection() {
|
||||
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 {
|
||||
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
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
add_msg("websocket客户端和服务器连接成功!");
|
||||
}
|
||||
|
||||
//收到服务端消息时触发
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
String[] s = message.split(" ");
|
||||
for (String s1 : s) {
|
||||
add_msg( s1 );
|
||||
add_msg(s1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//和服务端断开连接时触发
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote) {
|
||||
add_msg("websocket客户端退出连接");
|
||||
}
|
||||
|
||||
//连接异常时触发
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
|
|
@ -255,14 +330,15 @@ public class SSHConnectionController {
|
|||
}
|
||||
|
||||
public static void add_msg(String msg) {
|
||||
message_list.add(msg);
|
||||
message_list.add("------------------------------------------------------------------->");
|
||||
message_list.add(System.lineSeparator());
|
||||
// message_list.add(msg);
|
||||
// message_list.add("------------------------------------------------------------------->");
|
||||
// message_list.add(System.lineSeparator());
|
||||
}
|
||||
|
||||
public void receive(String msg) {
|
||||
Platform.runLater(() -> {
|
||||
this.show_result.setText(msg);
|
||||
// this.show_result.setText(msg);
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@ import javafx.scene.layout.AnchorPane;
|
|||
import javafx.scene.layout.HBox;
|
||||
import javafx.scene.paint.Paint;
|
||||
import javafx.scene.text.Font;
|
||||
import javafx.scene.web.WebView;
|
||||
import javafx.stage.Stage;
|
||||
import javafx.util.Callback;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
|
@ -284,6 +285,12 @@ public class ServerToolsController {
|
|||
root = ftpServer;
|
||||
}
|
||||
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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -2,9 +2,9 @@
|
|||
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextArea?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?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">
|
||||
<children>
|
||||
|
|
@ -14,12 +14,13 @@
|
|||
<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="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" />
|
||||
<Label layoutX="86.0" layoutY="181.0" text="显示:" AnchorPane.bottomAnchor="451.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="507.0" layoutY="131.0" text="端口:" />
|
||||
<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="连接" />
|
||||
<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" />
|
||||
<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" />
|
||||
<!-- <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>
|
||||
</AnchorPane>
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
|
|
@ -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 |
|
|
@ -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>
|
||||
Loading…
Reference in New Issue