本文出自明月工作室:https://www.freebytes.net/it/java/web-guacamole.html
简介
自上篇博客《Guacamole 开发web端远程桌面》写出来之后,陆续有伙伴联系我,希望我写一下guacamole的web集成版,可惜自己一直没什么心思,直到今日才终于想执笔了。
guacamole与web的集成方案
上篇博客说到,guacamole其实是分为客户端和服务端,服务端自不必管,依然使用上文介绍的方式去部署,也就是部署guacd。
客户端是一个war包,使用tomcat部署,所以客户端本身其实也是个独立的服务,它也包括了前端页面和后台代码,它的后台从guacd服务中获取数据,再通过js去渲染到页面。那么当我们自己的web系统想要集成guacamole时,其实也就是集成guacamole的客户端。对此,可能很多人想到一种集成方式——
让web系统与guacamole(包括客户端和服务端)系统独立部署,在web系统前端代码中用超链接的方式连接到guacamole的客户端页面。
但是,这种使用超链接跳转实现两个系统之间的过度的方式,却不能跳过guacamole客户端的登录页面,而且两个系统界面风格可能迥然不同,所以怎么看怎么别扭。
其实,guacamole是有提供web系统的集成包的,分为两部分,一个是js包 (guacamole-common-js,负责代替客户端的前端功能) ,一个是后台代码包( guacamole-common,负责代替客户端的后台功能 )。我们只需要将这两个包通过maven集成到自己的web系统中,就可以根据api调用了。
手写guacamole客户端
之所以先要手写一遍客户端,是为了更好地理解客户端的原理和作用,更好的实现集成。在做这部分工作之前,你需要保证官方的客户端和服务端在部署之后都能正常使用。然后建立一个空的maven项目,pom文件如下:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.yue</groupId> <artifactId>guacamole</artifactId> <version>1.0</version> <packaging>war</packaging> <name>guacamole-tutorial</name> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <!-- 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.0.0</version> <scope>compile</scope> </dependency> <!-- Guacamole JavaScript library --> <dependency> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-common-js</artifactId> <version>1.0.0</version> <type>zip</type> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <!-- Compile using Java 1.8 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.3</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-war-plugin</artifactId> <version>2.6</version> <configuration> <overlays> <overlay> <groupId>org.apache.guacamole</groupId> <artifactId>guacamole-common-js</artifactId> <type>zip</type> </overlay> </overlays> </configuration> </plugin> </plugins> </build> </project> //其中的jar包版本号,请自己根据最新的官方版本号更新。
理论上通过这pom文件,已经把guacamole相关的js和后台代码包导入,但是我这边有点问题,怎么也无法导入guacamole-common-js包,我这边想了个别的办法——直接找到maven本地仓库中的js包,解压出来,然后放到项目的webapp目录下。
然后,我们建立后台功能——新建java的servlet类:
import org.apache.guacamole.GuacamoleException; import org.apache.guacamole.net.GuacamoleSocket; import org.apache.guacamole.net.GuacamoleTunnel; import org.apache.guacamole.net.InetGuacamoleSocket; import org.apache.guacamole.net.SimpleGuacamoleTunnel; import org.apache.guacamole.protocol.ConfiguredGuacamoleSocket; import org.apache.guacamole.protocol.GuacamoleConfiguration; import org.apache.guacamole.servlet.GuacamoleHTTPTunnelServlet; import javax.servlet.http.HttpServletRequest; public class TutorialGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet { @Override protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { // Create our configuration GuacamoleConfiguration config = new GuacamoleConfiguration(); //远程桌面对象使用的远程协议 config.setProtocol("vnc"); //远程桌面对象的ip config.setParameter("hostname", "192.168.62.15"); //远程桌面对象的端口 config.setParameter("port", "5900"); // config.setParameter("password", "123456"); // Connect to guacd - everything is hard-coded here. GuacamoleSocket socket = new ConfiguredGuacamoleSocket( new InetGuacamoleSocket("192.168.80.122", 4822), config ); // Return a new tunnel which uses the connected socket return new SimpleGuacamoleTunnel(socket); } }
这个类便是用来连接guacd服务端和js客户端的桥梁。这个项目需要用tomcat启动,需要准备好web.xml文件:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"> <!-- Basic config --> <welcome-file-list> <welcome-file>index.html</welcome-file> </welcome-file-list> <!-- Guacamole Tunnel Servlet --> <servlet> <description>Tunnel servlet.</description> <servlet-name>Tunnel</servlet-name> <servlet-class> <!-- 与你新建的java类一致 --> com.yue.TutorialGuacamoleTunnelServlet </servlet-class> </servlet> <servlet-mapping> <servlet-name>Tunnel</servlet-name> <url-pattern>/tunnel</url-pattern> </servlet-mapping> </web-app>
然后建立前端页面,在webapp目录下新建index.html,前端页面需要引用guacamole-common-js——
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<title>Guacamole Tutorial</title>
</head>
<body>
<h1>千里明月的Gucamole</h1>
<!-- Guacamole -->
<script type="text/javascript"
src="guacamole-common-js/all.min.js"></script>
<!-- Display -->
<div id="display"></div>
<!-- Init -->
<script type="text/javascript"> /* <![CDATA[ */
// Get display div from document
var display = document.getElementById("display");
// Instantiate client, using an HTTP tunnel for communications.
//这里的“tunnel”与web.xml中配置的servlet-mapping对应
var guac = new Guacamole.Client(
new Guacamole.HTTPTunnel("tunnel")
);
// 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>
</body>
</html>
目前为止,我们借助maven引入了guacamole-common包,又手动解压了 guacamole-common-js的zip包放入到了web项目中,然后新建了后台隧道类,配置了servlet,又新建了前端页面,完整的项目目录如下:
接下来就是配置tomcat去启动了,可以利用idea配置好tomcat:
也可以直接打成war包,放到tomcat目录下启动,这里用的是idea的配置。
直接启动tomcat,输入 http://localhost:8086/guacamole/index.html 访问,便能看到192.168.62.15的远程桌面,并且可以用键盘和鼠标控制。
这里提供一下我的源码包吧—— https://www.freebytes.net/wp-content/uploads/files/guacamole.rar
集成guacamole客户端
经过手写guacamole之后,大家都应该知道了gaucamole的客户端包括些什么,我们自己的项目中又需要配置些什么、写些什么来调用它的功能。事实上,我们自己的web项目只需要引入两个包 guacamole-common 和 guacamole-common-js,然后提供一个通道servlet类,然后就是在一个html页面上调用js的事了,而这个html页面样式等也可以按你自己的设计来写。
所以,在一个web项目中,想要集成guacamole的客户端,无论是springboot项目还是外部tomcat项目,你都需要保证它可以使用servlet,然后引入两个包,在页面上调用相关的js,就是这么简单。我这里提供一下springboot项目集成guacamole客户端的完整步骤:
- 1、在application启动类中配置@ServletComponentScan({“net.freebytes.action”})扫描servlet类。
- 2、maven中引入两个关键包,像上文说的一样,如果不能引入js包,就把源码放到springboot的静态资源目录static下。
- 3、提供通道类——
@WebServlet(urlPatterns = "/net/freebytes/tunnel") public class TutorialGuacamoleTunnel extends GuacamoleHTTPTunnelServlet { @Autowired private ScreenProperties properties; @Override public GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException { String host = request.getParameter("host"); // Create our configuration GuacamoleConfiguration config = new GuacamoleConfiguration(); config.setProtocol("vnc"); config.setParameter("hostname", host); config.setParameter("port", "5900"); // config.setParameter("password", null); // Connect to guacd - everything is hard-coded here. GuacamoleSocket socket = new ConfiguredGuacamoleSocket( new InetGuacamoleSocket(properties.getGuacamoleServer(), properties.getGuacamolePort()), config ); // Return a new tunnel which uses the connected socket return new SimpleGuacamoleTunnel(socket); } }
- 4、在static目录下,新建freebytes.html,内容与上文的index.html差不多,但是有一点要注意,下面的”tunnel”要换成你在servlet类上设置的路径”/net/freebytes/tunnel”:
好了,大功告成!
既然已经实现了手写的guacamole客户端,并集成到了web端,那也就不用再部署guacamole那繁杂的客户端了。那么对于gaucamole的服务端guacd,有没有办法更方便的部署呢? 下篇文章中讲解如何使用《docker部署guacamole服务端》
能求一个从前端输入信息访问远程桌面的代码吗
现在我也在写这块功能 目前实现了复制黏贴, 连接状态监测 错误重连,但是网速检测不知道如何实现 连接在弱网环境极不稳定
大佬,声音相关的配置应该怎么弄?
按照文档的步骤我的远程连接没有声音,我查了部分文档,里面说如果不做额外处理视频和声音都是由guacamole-common-js自动处理的,想问一下大家都有声音吗?
怎么添加上传下载,粘贴呢大佬
大佬,按照你的教程。我启动了。但是访问没有任何效果。可惜不能截图给你看。
多个窗口同时连接有实现吗?
本来就有的
大佬,按照你的教程。我启动了。但是访问没有任何效果
想看作者丰富远程桌面功能 分辨率 剪贴板 上传下载这些😂
网页运行成功了 但是窗口分辨率太小了 请问在哪里设置分辨率
想问下作者如何添加上传和下载功能
想问下作者如何添加上传和下载功能
我这边使用python django 然后在ubuntu 安装的vnc-server
但是 链接不上
大佬,我这个看js代码扒出来方法了,如果别的小伙伴也需要前端输入的话,在guac.connect()方法,把要传的数据放在里面就好,格式是’xxx=1&yyy=2’这种的,里面是XMLHttpRequest.send(data)方法。底下那几个不用回复我了
最后那个使用客户端的后端代码是接收的前端的数据,可是这个你没有放前端代码啊
哪里有输入的地方啊,不是直接请求的后端,然后后端写死的吗,从哪里可以输入啊
怎样把ip等信息传到后端呢,想实现从前端输入用户名和密码来远程连接
我这个demo 不就是从前端输入用户名和密码来远程连接的嘛
问一下,我弄完之后,网页只显示了一个鼠标,没有界面是怎么回事
我这个是在vue框架下弄的
你试下能不能telnet通guacamole服务机的4822端口
不用vue的话是没问题的
是可以连通的,用你的那个demo是可以成功的,但是照着你的那个demo放在vue里面就不出界面,是连接成功的,就是没有画面
成功了。谢谢
用vnc 连进去是黑窗口是啥意思哦
你用vnc viewer连进去,也是黑屏吗
走vnc 协议 连进去 无权限 操作应用?
boot工程跑一直有问题 是咋会事
—–请求开始——-
2020-11-04 09:31:54.829 [io-12311-exec-2] DEBUG c.g.y.e.s.g.MyInetGuacamoleSocket [MyInetGuacamoleSocket.java:72] –
Connecting to guacd at 192.168.137.33:4822.
2020-11-04 09:32:02.140 [pool-2-thread-1] DEBUG c.g.y.e.s.g.MyInetGuacamoleSocket [MyInetGuacamoleSocket.java:104] –
Closing socket to guacd.
先telnet一下192.168.137.33 4822 看是否成功
可以了 ,但现在进入 页面后 用录屏软件录屏退出在进去后 发现中断了,大佬对此怎么解决的
我把这个用在vue中,发送请求的时候readyState和status分别是1和0,请教一下为什么会这样
的确是报500, tunnel?connect这个请求 500错误
HTTP Status 500 – Dangling meta character ‘?’ near index 0
我比较新手,普通的guacamole我会搭。但是想弄demo直接访问。所以想问大佬能不能做个视频教学<(︶︿︶)_╭∩╮╭∩╮
键盘无法输入呀
大佬,下载你的源码到idea中,run时候出现一系列“Error:(3, 28) java: 程序包org.apache.guacamole不存在;Error:(4, 32) java: 程序包org.apache.guacamole.net不存在等build 错误,请不吝指点一下,qq:2112727313,非常感谢!
你要引进org.apache.guacamole那个dependency依赖啊,我在文章前面的pom文件那部分有写
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(“192.168.80.122”, 4822),
config
这里连接不上呀
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket(“192.168.80.122”, 4822),
config
这里的host,端口要填写什么呀,我用的阿里云服务器部署的guacd,ip都试了,还是在这里连接不上
你应该先试一下telnet命令,能否连接到阿里云服务器的4822端口,如果不能,就要看下是不是端口没开放,或者guacd根本没启动成功
500 Internal Server Error
运行项目后500
能说具体些吗 可以把错误完整的复制一下发上来
学到了,感谢大神