SpringBoot整合Guacamole教程
前言
本文主要介绍的是SpringBoot如何整合Guacamole在浏览器是远程桌面的访问。
Guacamole 介绍
Apache Guacamole 是一个无客户端远程桌面网关。它支持标准协议,如 VNC、RDP 和 SSH。我们称之为无客户端,因为不需要插件或客户端软件。
用户使用他们的网络浏览器连接到 Guacamole 服务器。用 JavaScript 编写的 Guacamole 客户端由 Guacamole 服务器内的网络服务器提供给用户。加载后,此客户端使用 Guacamole 协议通过 HTTP 连接回服务器。部署到 Guacamole 服务器的 Web 应用程序读取 Guacamole 协议并将其转发到 guacd,即原生的 Guacamole 代理。这个代理实际上解释了 Guacamole 协议的内容,代表用户连接到任意数量的远程桌面服务器。Guacamole 协议与 guacd 结合提供了协议不可知性:Guacamole 客户端和 Web 应用程序都不需要知道实际使用的是什么远程桌面协议。
架构图如下:

协议
Web 应用程序根本不了解任何远程桌面协议。它不包含对 VNC 或 RDP 或由 Guacamole堆栈支持的任何其他协议的支持。它其实只懂Guacamole协议,这是一个用于远程显示渲染和事件传输的协议。虽然具有这些属性的协议自然具有与远程桌面协议相同的能力,但远程桌面协议和 Guacamole 协议背后的设计原则是不同的:Guacamole 协议并非旨在实现特定桌面环境的功能。
作为远程显示和交互协议,Guacamole 实现了现有远程桌面协议的超集。因此,向 Guacamole 添加对特定远程桌面协议(如RDP)的支持涉及编写一个中间层,在远程桌面协议和 Guacamole 协议之间进行“转换”。实现这样的转换与实现任何本地客户端没有什么不同,只是这个特定的实现呈现到远程显示器而不是本地显示器。
处理这种翻译的中间层是 guacd。
guacd
guacd 是 Guacamole 的核心,它动态加载对远程桌面协议(称为“客户端插件”)的支持,并根据从 Web 应用程序收到的指令将它们连接到远程桌面。 guacd 是一个守护进程,它与 Guacamole 一起安装并在后台运行,监听来自 Web 应用程序的 TCP 连接。guacd 也不理解任何特定的远程桌面协议,而是实现了足够的 Guacamole 协议来确定需要加载哪些协议支持以及必须将哪些参数传递给它。加载客户端插件后,它会独立于 guacd 运行,并完全控制自身与 Web 应用程序之间的通信,直到客户端插件终止。 guacd 和所有客户端插件都依赖于一个公共库 libguac,这使得通过 Guacamole
协议进行的通信更容易也更抽象一些。
网络应用程序
用户实际与之交互的 Guacamole 部分是 Web 应用程序。
如前所述,Web 应用程序没有实现任何远程桌面协议。它依赖于 guacd,并且仅实现了一个漂亮的 Web 界面和身份验证层。
我们选择用 Java 实现 Web 应用程序的服务器端,但没有理由不能用不同的语言编写。事实上,因为 Guacamole 旨在成为一个 API,我们鼓励这样做。
RealMint
Guacamole 现在是一个通用的远程桌面网关,但情况并非总是如此。Guacamole最初是用 JavaScript 编写的纯文本 Telnet 客户端,称为 RealMint(“RealMint”是“终端”的字谜)。它主要是为了演示而编写的,虽然目的是有用,但它的主要名声只是因为它是纯 JavaScript。
RealMint 使用的隧道是用 PHP 编写的。与 Guacamole 的 HTTP 隧道相比,RealMint 的隧道仅使用简单的长轮询,效率低下。RealMint 有一个不错的键盘实现,现在在 Guacamole 的键盘代码的一部分中存在,但这实际上是 RealMint 的功能和可用性的范围。鉴于它只是一个遗留协议的实现,并且存在其他几个 JavaScript 终端模拟器,其中大多数已经建立和稳定,该项目被放弃了。
VNC客户端
一旦开发人员了解了 HTML5 canvas 标签,并看到它已经在 Firefox 和 Chrome 中实现,就开始在概念验证JavaScript VNC 客户端上开展工作。
这个客户端是带有 Java 服务器组件的纯 JavaScript,通过将 VNC 转换为相同的基于 XML 的版本来工作。它的发展自然是由VNC 的特性驱动的,它的范围仅限于将单个连接转发给一组用户。尽管相对较慢,但概念验证运行良好,以至于该项目需要一个在线住所,并在SourceForge 上注册为“Guacamole”——一个 HTML5 VNC 客户端。
随着 Guacamole 的发展并不仅仅是一个概念验证,对速度的需求也增加了,旧的 RealMint 风格的长轮询被放弃了,XML 的使用也是如此。
由于当时无法信任 WebSocket 得到支持,并且 Java 没有用于 servlet 的 WebSocket 标准,因此开发了一个等效的基于 HTTP 的隧道。如果 WebSocket 因任何原因无法使用,此隧道今天仍在使用。
远程桌面网关
开发了一种更快的基于文本的协议,它可以呈现多个远程桌面协议的功能,而不仅仅是 VNC。整个系统被重新构建为一个标准守护进程 guacd 和一个公共库 libguac,后者驱动守护进程和协议支持,并变得可扩展。 该项目的范围从一个足够的 VNC 客户端扩展到一个高性能的 HTML5 远程桌面网关和通用 API。在目前的状态下,Guacamole可以用作中央网关来访问运行不同远程桌面服务器的任意数量的机器。它提供可扩展的身份验证,如果您需要更专业的东西,则可以使用用于基于 HTML5 的远程访问的通用 API。
官网:http://guacamole.apache.org/
Guacamole 安装
参考官网安装: https://guacamole.apache.org/doc/gug/users-guide.html
建议使用docker安装,可以快速安装,docker安装教程:https://www.cnblogs.com/xuwujing/p/15073174.html
Apache Guacamole分为服务端和客户端,均在同一服务器上部署。
首先是下载镜像,Guacamole数据库可以选择mysql或 PostgreSQL
docker pull guacamole/guacamole
docker pull guacamole/guacd
docker pull mysql/mysql-server
然后初始化mysql以及对mysql进行相关配置。
docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
docker run --name mysql --restart=always -e MYSQL_ROOT_PASSWORD=123456 -d mysql/mysql-server:5.7
docker cp initdb.sql mysql:/initdb.sql
sudo docker exec -it mysql mysql -uroot -p123456
CREATE DATABASE guacamole;
CREATE USER 'guacamole'@'%' IDENTIFIED BY 'guacamole';
GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole.* TO 'guacamole'@'%';
FLUSH PRIVILEGES;
quit
docker exec -it mysql bashmysql –uroot –p123456 -Dguacamole<initdb.sql ```="" 依次启动:="" docker="" run="" --name="" guacd="" --restart="always" -d="" guacamole="" --link="" guacd:guacd="" mysql:mysql="" -e="" mysql_database="guacamole" mysql_user="guacamole" mysql_password="guacamole" -p="" 8080:8080="" " 可以用="" ps="" 命令查看是否启动成功!="" 启动成功之后,可以在浏览器上面输入:**http:="" ip:8080="" guacamole**="" 进行访问,默认的账号密码都是**guacadmin**;="" deba51affc8e48c48f04c38e4130f433.png?x-oss-process="image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FhendzeHBjbQ==,size_16,color_FFFFFF,t_70)" ##="" springboot整合guacamole="" 在整合之前,需要guacamole已经启动,且准备一台windows的远程机。="" 首先是核心pom文件:="" <dependency="">
<groupid>org.springframework.boot</groupid>
<artifactid>spring-boot-starter-websocket</artifactid>
<!-- Servlet API -->
<dependency>
<groupid>javax.servlet</groupid>
<artifactid>servlet-api</artifactid>
<version>2.5</version>
<scope>provided</scope>
</dependency>
<!-- Main Guacamole library -->
<dependency>
<groupid>org.apache.guacamole</groupid>
<artifactid>guacamole-common</artifactid>
<version>1.1.0</version>
</dependency>
<!-- Guacamole JavaScript library -->
<dependency>
<groupid>org.apache.guacamole</groupid>
<artifactid>guacamole-common-js</artifactid>
<version>1.1.0</version>
<type>zip</type>
<scope>runtime</scope>
</dependency>
示例代码可以从这里下载:http://guacamole.apache.org/api-documentation/
这里我选择的是java和js,这里必须要下载js文件,本篇文章示例在末尾,可以直接下载。

准备好了,编写如下代码,在示例代码有,这里使用的是webSocket,也可以选择http方式建立连接。
Java代码如下:
@ServerEndpoint(value = "/webSocket", subprotocols = "guacamole")
@Component
public class WebSocketTunnel extends GuacamoleWebSocketTunnelEndpoint {
/**
* Returns a new tunnel for the given session. How this tunnel is created
* or retrieved is implementation-dependent.
*
* @param session The session associated with the active WebSocket
* connection.
* @param endpointConfig information associated with the instance of
* the endpoint created for handling this single connection.
* @return A connected tunnel, or null if no such tunnel exists.
* @throws GuacamoleException If an error occurs while retrieving the
* tunnel, or if access to the tunnel is denied.
*/
@Override
protected GuacamoleTunnel createTunnel(Session session, EndpointConfig endpointConfig) throws GuacamoleException {
//guacamole server地址 端口
String hostname = "192.168.0.1";
int port = 4822;
GuacamoleConfiguration configuration = new GuacamoleConfiguration();
configuration.setProtocol("rdp");
// 远程windows服务的地址
configuration.setParameter("hostname", "192.168.0.2");
configuration.setParameter("port", "3389");
configuration.setParameter("username", "administrator");
configuration.setParameter("password", "123456");
configuration.setParameter("ignore-cert", "true");
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(hostname, port),
configuration
);
GuacamoleTunnel tunnel = new SimpleGuacamoleTunnel(socket);
return tunnel;
}
JavaScript代码主要是引用下载的js,使用http的话,核心使用代码就是:
var guac = new Guacamole.Client(
new Guacamole.HTTPTunnel("tunnel")
);
WebSocket 代码如下:
var guac = new Guacamole.Client(
new Guacamole.WebSocketTunnel("webSocket")
);
完整代码如下:
<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
-->
<link rel="stylesheet" type="text/css" href="guacamole.css">
<title>Guacamole (EXAMPLE)</title>
<h1>pancm Guacamole</h1>
<!-- Display -->
<div id="display"></div>
<!-- Guacamole JavaScript API -->
<script type="text/javascript" src="guacamole-common-js/all.min.js"></script>
<!-- Init -->
<script type="text/javascript"> /* <![CDATA[ */
// Get display div from document
var display = document.getElementById("display");
// Instantiate client, using an HTTP tunnel for communications.
// httl方式
var guac = new Guacamole.Client(
new Guacamole.HTTPTunnel("tunnel")
);
// WebSocket 方式
var guac = new Guacamole.Client(
new Guacamole.WebSocketTunnel("webSocket")
);
// Add client to display div
display.appendChild(guac.getDisplay().getElement());
// Error handler
guac.onerror = function(error) {
alert(error);
};
// Connect
guac.connect();
// Disconnect on close
window.onunload = function() {
guac.disconnect();
}
// Mouse
var mouse = new Guacamole.Mouse(guac.getDisplay().getElement());
mouse.onmousedown =
mouse.onmouseup =
mouse.onmousemove = function(mouseState) {
guac.sendMouseState(mouseState);
};
// Keyboard
var keyboard = new Guacamole.Keyboard(document);
keyboard.onkeydown = function (keysym) {
guac.sendKeyEvent(1, keysym);
};
keyboard.onkeyup = function (keysym) {
guac.sendKeyEvent(0, keysym);
};
/* ]]> */ </script>
编写完毕之后,我们启动程序,在浏览器上面输入localhost:9632/api 即可进行远程桌面。
示例图:

如何进行前后端分离
前后端在示例代码中是未分离的,如果进行分离的话, 在http或WebSocket请求的前面加上ip和端口即可。
如下:
var guac = new Guacamole.Client(
new Guacamole.WebSocketTunnel("ws://192.168.0.1:9632/api/webSocket")
);
WebSocket方式如何传递参数以及取值
前端js在请求的url后面加上?key=value&key2=value2& 即可.
示例如下:
var guac = new Guacamole.Client(
new Guacamole.WebSocketTunnel("ws://192.168.0.1:9632/api/webSocket?ip=192.168.0.1&")
);
后端取值代码示例:
String ip = session.getRequestParameterMap().get("ip").get(0);
如何设置屏幕宽高
在后端代码中,添加如下配置:
GuacamoleClientInformation information = new GuacamoleClientInformation();
information.setOptimalScreenHeight(height);
information.setOptimalScreenWidth(width);
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(hostname, port),
configuration,
information
);
如何设置录屏
在后端代码中,添加如下配置:
String fileName = getNowTime() + ".guac";//文件名
String outputFilePath = "/home/guacamole";
//添加会话录制--录屏
configuration.setParameter("recording-path", outputFilePath);
configuration.setParameter("create-recording-path", "true");
configuration.setParameter("recording-name", fileName);
录屏的文件是.guac,我们需要对其进行解码,命令如下:
guacenc 文件名称
当然也可以对其设置参数配置,示例图如下:

如果对生成的文件格式不满意,想转码的话,可以使用ffmpeg进行转码。
如何关闭远程桌面
关闭后端的session即可。代码如下:
private void optClose(Session session) {
// 判断当前连接是否还在线
if (session.isOpen()) {
try {
// 关闭连接
CloseReason closeReason = new CloseReason(CloseReason.CloseCodes.NORMAL_CLOSURE, "进行关闭!");
session.close(closeReason);
} catch (IOException e) {
e.printStackTrace();
}
}
}
其他开源远程桌面工具介绍
Teleport
Teleport是一款简单易用的堡垒机系统,具有小巧、易用的特点,支持 RDP/SSH/SFTP/Telnet 协议的远程连接和审计管理。
Teleport由两大部分构成:
跳板核心服务 WEB操作界面
安装方式
下载地址:
https://www.tp4a.com/download
Teleport 也是分为服务端和客户端,服务端安装如下,下载好文件之后,上传在linux服务中进行安装,命令如下:
tar -zxvf teleport-linux-3.0.2.9.tar.gz
cd teleport-linux-3.0.2.9
sudo ./setup.sh
相关命令:
启动: /etc/init.d/teleport start
停止: /etc/init.d/teleport stop
重启: /etc/init.d/teleport restart
查看运行状态: /etc/init.d/teleport status
客户端主要是在进行远程桌面操作和录像回放的时候使用, 安装直接下载到本地运行即可。
启动之后在浏览器输入:http://teleport服务器IP:7190/ 进行配置即可。

更多请查阅官网!
官网地址: https://docs.tp4a.com/
JumpServer
JumpServer 使用 Python / Django 为主进行开发,遵循 Web 2.0 规范,配备了业界领先的 Web
Terminal 方案,交互界面美观、用户体验好。JumpServer 采纳分布式架构,支持多机房跨区域部署,支持横向扩展,无资产数量及并发限制。
更多详细了解请查阅官网。
官网地址:https://www.jumpserver.org/

其他
项目地址
项目工程地址:
https://github.com/xuwujing/springBoot-study/tree/master/springboot-guacamole
SpringBoot整个集合的地址:
https://github.com/xuwujing/springBoot-study
SpringBoot整合系列的文章
音乐推荐
原创不易,如果感觉不错,希望给个推荐!您的支持是我写作的最大动力!
版权声明:
作者:虚无境
博客园出处:http://www.cnblogs.com/xuwujing
CSDN出处:http://blog.csdn.net/qazwsxpcm
个人博客出处:http://www.panchengming.com
</initdb.sql>
SpringBoot整合Guacamole教程的更多相关文章
- 很详细的SpringBoot整合UEditor教程
很详细的SpringBoot整合UEditor教程 2017年04月10日 20:27:21 小宝2333 阅读数:21529 版权声明:本文为博主原创文章,未经博主允许不得转载. https: ...
- 最简单的SpringBoot整合MyBatis教程
前面两篇文章和读者聊了Spring Boot中最简单的数据持久化方案JdbcTemplate,JdbcTemplate虽然简单,但是用的并不多,因为它没有MyBatis方便,在Spring+Sprin ...
- Springboot 整合RabbitMq ,用心看完这一篇就够了
该篇文章内容较多,包括有rabbitMq相关的一些简单理论介绍,provider消息推送实例,consumer消息消费实例,Direct.Topic.Fanout的使用,消息回调.手动确认等. (但是 ...
- java springboot整合zookeeper入门教程(增删改查)
java springboot整合zookeeper增删改查入门教程 zookeeper的安装与集群搭建参考:https://www.cnblogs.com/zwcry/p/10272506.html ...
- SpringBoot整合Quartz定时任务 系统job Spring Boot教程 调度任务
原文地址:https://www.cnblogs.com/allalongx/p/8477368.html 构建工程 创建一个Springboot工程,在它的程序入口加上@EnableScheduli ...
- SpringBoot非官方教程 | 第九篇: springboot整合Redis
转载请标明出处: 原文首发于:https://www.fangzhipeng.com/springboot/2017/07/11/springboot9-redis/ 本文出自方志朋的博客 这篇文章主 ...
- Spring Boot2 系列教程(十七)SpringBoot 整合 Swagger2
前后端分离后,维护接口文档基本上是必不可少的工作. 一个理想的状态是设计好后,接口文档发给前端和后端,大伙按照既定的规则各自开发,开发好了对接上了就可以上线了.当然这是一种非常理想的状态,实际开发中却 ...
- springboot整合apache ftpserver详细教程(看这一篇就够了)
原创不易,如需转载,请注明出处https://www.cnblogs.com/baixianlong/p/12192425.html,否则将追究法律责任!!! 一.Apache ftpserver相关 ...
- Springboot整合Redis入门完整篇,零基础入门教学教程
记录一次简易集成Redis缓存 自定义Redisconfig配置 自定义序列化操作 加深印像 整合前提工具环境准备: 1.redis官网 https://redis.io/download 下载安装r ...
随机推荐
- VBS脚本编程(1)——数据类型、变量和常量
数据类型 VBS只有一种数据类型,称为Variant.而该类型是可变的,以下是Variant的子类型: 子类型 描述 Empty 未初始化的Variant.对于数值变量,值为0:对于字符串变量,值为零 ...
- JAVA设计模式(6:单例模式详解)
单例模式作为一种创建型模式,在日常开发中用处极广,我们先来看一一段代码: // 构造函数 protected Calendar(TimeZone var1, Locale var2) { this.l ...
- 基于ILI9341的TFT液晶显示模组LCM240320详解(1)
Hello,大家好,今天我们来讨论当下非常流行的TFT液晶显示模组,它最大的特点是可以显示出效果非常好的彩色信息,绝大多数手机.液晶显示器,液晶电视.MID.MP4等产品都在使用它,你想抗拒它的魅力还 ...
- Linux定时任务-cronie
1.cronie服务介绍 Linux crontab(cronie)是用来定期执行程序的命令. 当安装完成操作系统之后,默认就会启动此任务调度命令. crond 命令每分钟会定期检查是否有要执行的工作 ...
- 基于C#的socket编程的TCP同步实现
该博客源著地址https://www.cnblogs.com/sunev/archive/2012/08/05/2604189.html 一.摘要 总结一下基于C#的TCP传输协议的涉及到的常用方法及 ...
- 28、windows下通过MSI图形界面方式安装mysql
28.1.下载mysql: 1. www.mysql.com 2. 3. https://dev.mysql.com/downloads/mysql/ 4. 5. 28.2.安装: 双击下载的&quo ...
- hdu 2159 二维完全背包
Problem Description 最近xhd正在玩一款叫做FATE的游戏,为了得到极品装备,xhd在不停的杀怪做任务.久而久之xhd开始对杀怪产生的厌恶感,但又不得不通过杀怪来升完这最后一级.现 ...
- Spring:Spring注解大全
@Controller 标识一个该类是Spring MVC controller处理器,用来创建处理http请求的对象. @Controller public class TestController ...
- Spring:Spring嵌套事务方式
Spring遇到嵌套事务时,怎么实现 实验时却遇到一个奇怪的问题: 1.当ServiceA.a()方法调用ServiceB.b()方法时,内层事务提交和回滚,都不受外层事务提交或回滚的影响. 2.当S ...
- XCTF crypto 不仅仅是Mors
一. 题目暗示摩斯码,打开文件发现里面有反斜杠的.不管它直接拿来解密 二. 发现一句话是句英文,还有其他的加密方式,后面那串只有两种字符A和B,手抓饼A套餐,b套餐 培根加密,拿来解密后,得到flag