ubuntu部署Guacamole,Guacamole集成springboot,vue
<h2 id="前言">前言</h2><p>本文主要介绍的是如何docker安装Guacamole,进行浏览器远程桌面的访问。</p>
<h2 id="guacamole">Guacamole</h2>
<blockquote>
<p>Apache Guacamole 是一个无客户端远程桌面网关。它支持标准协议,如 VNC、RDP 和 SSH。我们称之为无客户端,因为不需要插件或客户端软件。<br>
用户使用他们的网络浏览器连接到 Guacamole 服务器。用 JavaScript 编写的 Guacamole 客户端由 Guacamole 服务器内的网络服务器提供给用户。加载后,此客户端使用 Guacamole 协议通过 HTTP 连接回服务器。部署到 Guacamole 服务器的 Web 应用程序读取 Guacamole 协议并将其转发到 guacd,即原生的 Guacamole 代理。这个代理实际上解释了 Guacamole 协议的内容,代表用户连接到任意数量的远程桌面服务器。Guacamole 协议与 guacd 结合提供了协议不可知性:Guacamole 客户端和 Web 应用程序都不需要知道实际使用的是什么远程桌面协议</p>
</blockquote>
<h2 id="协议">协议</h2>
<blockquote>
<p>Web 应用程序根本不了解任何远程桌面协议。它不包含对 VNC 或 RDP 或由 Guacamole堆栈支持的任何其他协议的支持。它其实只懂Guacamole协议,这是一个用于远程显示渲染和事件传输的协议。虽然具有这些属性的协议自然具有与远程桌面协议相同的能力,但远程桌面协议和 Guacamole 协议背后的设计原则是不同的:Guacamole 协议并非旨在实现特定桌面环境的功能。<br>
作为远程显示和交互协议,Guacamole 实现了现有远程桌面协议的超集。因此,向 Guacamole 添加对特定远程桌面协议(如RDP)的支持涉及编写一个中间层,在远程桌面协议和 Guacamole 协议之间进行“转换”。实现这样的转换与实现任何本地客户端没有什么不同,只是这个特定的实现呈现到远程显示器而不是本地显示器。<br>
处理这种翻译的中间层是 guacd</p>
</blockquote>
<h2 id="guacd">guacd</h2>
<blockquote>
<p>guacd 是 Guacamole 的核心,它动态加载对远程桌面协议(称为“客户端插件”)的支持,并根据从 Web 应用程序收到的指令将它们连接到远程桌面。 guacd 是一个守护进程,它与 Guacamole 一起安装并在后台运行,监听来自 Web 应用程序的 TCP 连接。guacd 也不理解任何特定的远程桌面协议,而是实现了足够的 Guacamole 协议来确定需要加载哪些协议支持以及必须将哪些参数传递给它。加载客户端插件后,它会独立于 guacd 运行,并完全控制自身与 Web 应用程序之间的通信,直到客户端插件终止。 guacd 和所有客户端插件都依赖于一个公共库 libguac,这使得通过 Guacamole<br>
协议进行的通信更容易也更抽象一些。</p>
</blockquote>
<h2 id="ultravnc">UltraVNC</h2>
<blockquote>
<p>UltraVNC是一款功能强大、易于使用且免费的远程 PC 访问软件,它可以在您自己的屏幕上显示另一台计算机的屏幕(通过互联网或网络)。该程序允许您使用鼠标和键盘远程控制另一台 PC。这意味着您可以在远程计算机上工作,就好像您坐在它前面一样,就在您当前的位置。</p>
<p>VNC,即远程帧缓冲协议 (RFB),允许通过 Internet 远程查看和控制桌面。VNC 服务器必须运行在共享桌面的计算机上,VNC 客户端必须运行在将访问共享桌面的计算机上</p>
</blockquote>
<h2 id="安装-guacamole-所需的环境">安装 Guacamole 所需的环境</h2>
<p>本文编写环境: window11专业版 + VMware + Ubuntu官网最新版镜像虚拟机( 22.04 LTS)</p>
<p>docker安装教程: https://www.runoob.com/docker/ubuntu-docker-install.html</p>
<p>官网使用docker安装: https://guacamole.apache.org/doc/gug/guacamole-docker.html</p>
<p>docker推荐使用官方安装脚本自动安装</p>
<pre><code class="language-shell">curl -fsSL https://get.docker.com | bash -s docker --mirror Aliyun
</code></pre>
<p>输入以上命令即可</p>
<p>接下来就可以输入docker的命令进行测试了</p>
<h3 id="安装guacamole">安装Guacamole</h3>
<p>安装大体可以分为4部分:</p>
<ol>
<li>安装Guacamole镜像 + 需要的数据库镜像(mysql/PostgreSQL)</li>
<li>由Guacamole镜像生成容器</li>
<li>初始化数据库 + 关联各个容器</li>
<li>启动容器</li>
</ol>
<h4 id="安装guacamole镜像">安装Guacamole镜像</h4>
<pre><code class="language-shell">docker pull guacamole/guacd
docker pull guacamole/guacamole
docker pull mysql
</code></pre>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160139197-333804651.png" alt="" loading="lazy"></p>
<p>通过<code>docker images</code>命令可以看到目前已经有了3个镜像</p>
<h4 id="guacd容器初始化">guacd容器初始化</h4>
<pre><code class="language-shell">docker run --name guacd -d guacamole/guacd
</code></pre>
<p>guacd 将在其默认端口 4822 上进行侦听</p>
<h4 id="mysql容器初始化">mysql容器初始化</h4>
<pre><code class="language-shell">docker run -itd --name mysql -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 mysql
</code></pre>
<ul>
<li><strong>-p 3306:3306</strong> :映射容器服务的 3306 端口到宿主机的 3306 端口,外部主机可以直接通过 <strong>宿主机ip:3306</strong> 访问到 MySQL 的服务。</li>
<li><strong>MYSQL_ROOT_PASSWORD=123456</strong>:设置 MySQL 服务 root 用户的密码。</li>
</ul>
<p>通过 <strong>docker ps</strong> 命令查看<code>mysql</code>和<code>guacd</code>是否安装成功</p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160153987-307959555.png" alt="" loading="lazy"></p>
<p>由于<code>Guacamole</code>需要使用数据库来进行身份验证,所以我们还需要对mysql数据写入一个供<code>guacamole</code>访问的用户和数据库</p>
<p><code>guacamole</code>提供一个生成自己所需的sql文件供我们使用,使用以下的命令:</p>
<pre><code class="language-shell">docker run --rm guacamole/guacamole /opt/guacamole/bin/initdb.sh --mysql > initdb.sql
</code></pre>
<p>此命令会在你当前的文件夹下生成一个<code>initdb.sql</code>文件,比如你在桌面目录下执行的,那么你桌面上就会生成这样的一个文件</p>
<p>生成此脚本后,我们需要完成:</p>
<ol>
<li>为 Guacamole 创建一个数据库,例如<code>guacamole_db</code>.</li>
<li>为 Guacamole 创建一个可以访问此数据库的用户,例如<code>guacamole_user</code>.</li>
<li>在新创建的数据库上运行脚本</li>
</ol>
<p>现在我们进入数据库:</p>
<pre><code class="language-shell">//进入mysql容器
docker exec -it mysql /bin/bash
//进入数据库
mysql -uroot -p123456
//创建数据库
CREATE DATABASE guacamole_db;
//创建供Guacamole访问的用户,并赋予权限
//这里因为我们的mysql是用的容器,如果用@'localhost'到后面我们用宿主机进入后台的时候,是无法访问的,我们应该用'%'这个权限
//如果你的mysql是用的宿主机的mysql,那么可以试试localhost
CREATE USER 'guacamole_user'@'%' IDENTIFIED BY 'some_password';
GRANT SELECT,INSERT,UPDATE,DELETE ON guacamole_db.* TO 'guacamole_user'@'%';
//刷新用户
FLUSH PRIVILEGES;
//退出数据库
exit
//退出mysql容器内部
exit
//执行把宿主机的sql文件copy到mysql容器内部
//docker cp 要拷贝的文件路径 容器名:要拷贝到容器里面对应的路径
//我这里是因为我的文件就在桌面,如果你在其他目录下,填写路径就可以比如: /home/initdb.sql
docker cp initdb.sql mysql:/
//这个时候进入mysql容器查看文件
docker exec -it mysql bash
//此时应该就有这个sql文件了
ls
//执行mysql执行sql脚本
//语法: mysql –u用户名 –p密码 –D数据库 <
mysql -uroot -p123456 -Dguacamole_db<initdb.sql
//查看脚本是否执行成功
//进入数据库
mysql -uroot -p123456
//查看数据库
show databases;
//进入guacamole_db数据库
use guacamole_db;
//查看guacamole_db表
show tables;
//如果看到十几个表就证明执行成功了
//退出mysql和容器
exit
exit
</code></pre>
<h4 id="guacamole容器初始化">guacamole容器初始化</h4>
<pre><code class="language-shell">//请先不要执行,先看参数解析
docker run --name guacamole --restart=always--link guacd:guacd --link mysql:mysql -e MYSQL_DATABASE=guacamole_db -e MYSQL_USER=guacamole_user -e MYSQL_PASSWORD=some_password -d -p 9090:8080 guacamole/guacamole
</code></pre>
<ol>
<li><code>--link guacd:guacd</code> 使Guacamole容器和guacd容器关联,这个地方冒号前面的guacd是你创建这个容器时指定的name参数</li>
<li><code>--link mysql:mysql</code> 使Guacamole容器和mysql容器管理,这个地方冒号前面的guacd是你创建这个容器时指定的name参数</li>
<li><code>-e MYSQL_DATABASE=guacamole_db</code> 上面初始化数据库时,创建的guacamole_db数据库</li>
<li><code>-e MYSQL_USER=guacamole_user</code> 上面初始化用户时,创建的guacamole_user用户</li>
<li><code>-e MYSQL_PASSWORD=song_password</code> 上面初始化用户密码时,创建的some_password密码</li>
<li><code>-p 9090:8080</code> 绑定宿主机的9090端口</li>
</ol>
<p>如果上面的操作中,创建的用户名、数据库名、密码不同的话请自行更改</p>
<p>其他额外的一些参数,如果严格按照上文的步骤是不需要的:</p>
<p><code>MYSQL_HOSTNAME</code> 用于 Guacamole 身份验证的数据库的主机名。<em>如果您不使用 Docker 来提供 MySQL 数据库,则这是必需的</em></p>
<p><code>MYSQL_PORT</code> Guacamole 在连接到 MySQL 时应该使用的端口。此环境变量是可选的。如果未提供,将使用标准 MySQL 端口 3306</p>
<p>此时可以执行<code>docker ps</code> 查看三个容器是否都正常执行</p>
<p>如果都启动成功了,那么就可以在宿主机上打开浏览器输入<strong>http://localhost:9090/guacamole</strong>,来进入后台管理页面,默认账号密码都是<strong>guacadmin</strong></p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160207288-1919440790.png" alt="" loading="lazy"></p>
<h3 id="常见打不开后台报错">常见打不开后台报错</h3>
<ul>
<li>如果3个容器全部都正常启动,那么还是访问不了后台,比如我们访问localhost:9090也没有显示tomcat的404的标志,那可能是宿主机的端口映射没有被容器的端口映射上,如果你也是虚拟机环境,试试重启一下</li>
</ul>
<p>重启之后我们需要重启启动容器</p>
<pre><code class="language-shell">docker ps -a
docker start mysql
docker start guacd
docker start guacamole
docker ps -a
</code></pre>
<ul>
<li>如果不能访问后台,我们需要先检查数据库的初始化表是否都正常初始化,用我们创建的用户,登录一遍mysql看看是否正确</li>
</ul>
<p>如果mysql没有问题,那么我们就需要看看<code>guacamole</code>容器的报错日志</p>
<pre><code class="language-shell">docker logs 容器id
</code></pre>
<p>看看日志里面有没有什么报错,比如无法连接数据库之类的问题</p>
<ul>
<li>Cause: java.sql.SQLException: Access denied for user 'guacamole_user'@'172.17.0.4' (using password: YES)</li>
</ul>
<p>解决:如果在mysql创建用户的时候,权限使用的localhost的话,使用docker-mysql容器连接的话,是代表不了localhost的,需要使用%</p>
<ul>
<li>如果我们挂起了虚拟机,然后再次使用的时候,会发现打不开后台了,这个时候也是需要重新启动下虚拟机,然后重启下容器即可</li>
</ul>
<h2 id="使用drp方式测试远程连接">使用DRP方式测试远程连接</h2>
<p>云服务器配置:win10服务器版本 非window版本可以试试SSH连接</p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160218218-2078036350.png" alt="" loading="lazy"></p>
<p>点击设置</p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160226070-200148239.png" alt="" loading="lazy"></p>
<p>创建一个RDP连接</p>
<p>编辑连接:</p>
<ul>
<li>名称:随便起</li>
<li>位置:用默认的root就行</li>
<li>协议:RDP</li>
</ul>
<p>参数:</p>
<p> 网络:</p>
<ul>
<li>主机名: 要被连接的主机ip</li>
<li>端口:支持RDP连接的window端口都默认是3389</li>
</ul>
<p>认证:</p>
<ul>
<li>用户名:远程服务器的用户名,云服务器默认用户名为: Administrator</li>
<li>密码:服务器密码</li>
<li>忽略服务器证书:这个要勾上</li>
</ul>
<p>直接到最下面保存即可</p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160234617-648531270.png" alt="" loading="lazy"></p>
<p>来到首页,找到我们刚刚新建的连接,双击即可,等待连接成功</p>
<h2 id="使用vnc方式测试远程连接">使用VNC方式测试远程连接</h2>
<p>云服务器环境:window10服务器版本非window版本可以试试SSH连接</p>
<p>创建一个VNC连接</p>
<p>编辑连接:</p>
<ul>
<li>名称:随便起</li>
<li>位置:用默认的root就行</li>
<li>协议:VNC</li>
</ul>
<p>参数:</p>
<p> 网络:</p>
<ul>
<li>主机名: 要被连接的主机ip</li>
<li>端口:安装的VNCServe 默认端口是5900</li>
</ul>
<p>认证:</p>
<ul>
<li>用户名:远程服务器的用户名,云服务器默认用户名为: Administrator</li>
<li>密码:安装的VNCServe里面的VNC密码</li>
</ul>
<p>直接到最下面保存即可</p>
<p><strong>这个时候我们只是创建了一个连接,我们还需要在被远程的机器上安装UltraVNC工具,下文有一章会介绍如何安装使用</strong></p>
<h2 id="使用drp方式连接内网window机器">使用DRP方式连接内网window机器</h2>
<p>测试window版本:win10 + 专业版本</p>
<p>创建一个DRP连接</p>
<p>编辑连接:</p>
<ul>
<li>名称:随便起</li>
<li>位置:用默认的root就行</li>
<li>协议:DRP</li>
</ul>
<p>参数:</p>
<p> 网络:</p>
<ul>
<li>主机名: 要被连接的主机ip</li>
<li>端口:默认3389</li>
<li>忽略服务器证书:这个要勾上</li>
</ul>
<p>认证:</p>
<ul>
<li>用户名:电脑用户名,</li>
<li>密码:电脑密码</li>
</ul>
<p>直接到最下面保存即可</p>
<p>这个地方如果你要访问的机器没有用户名和密码全部空着即可</p>
<p><strong>如果访问不通,请把被访问机器里面的防火墙关掉或者把3389这个端口开通</strong></p>
<p><strong>打开被访问机器里面关于运行被远程控制等选项</strong></p>
<p><strong>win10家庭版不支持远程,所以无法使用DRP和VNC方式</strong></p>
<p><strong>如果有绑定微软账号,那么用户名其实是你微软账号的用户名,密码同理,如果你电脑开通了PIN登录,但是你需要输入的密码还是微软账号的密码</strong></p>
<p><strong>如果我们附加没有第二台机器供我们测试,我们可以测试用虚拟机里面的机器远程连接我们本机,PRD的方式会在连接成功后的几秒显示有冲突而退出PRD,VNC方式可以套娃一直连接</strong></p>
<h2 id="使用vnc方式连接内网window机器">使用VNC方式连接内网window机器</h2>
<p>测试window版本:win10 + 专业版本</p>
<p>创建一个VNC连接</p>
<p>编辑连接:</p>
<ul>
<li>名称:随便起</li>
<li>位置:用默认的root就行</li>
<li>协议:VNC</li>
</ul>
<p>参数:</p>
<p> 网络:</p>
<ul>
<li>主机名: 要被连接的主机ip</li>
<li>端口:安装的VNCServe 默认端口是5900</li>
</ul>
<p>认证:</p>
<ul>
<li>用户名:电脑用户名,</li>
<li>密码:安装的VNCServe里面的VNC密码</li>
</ul>
<p>直接到最下面保存即可</p>
<p>这个地方如果你要访问的机器没有用户名和密码全部空着即可</p>
<p><strong>如果访问不通,请把被访问机器里面的防火墙关掉或者把3389这个端口开通</strong></p>
<p><strong>打开被访问机器里面关于运行被远程控制等选项</strong></p>
<p><strong>win10家庭版不支持远程,所以无法使用DRP和VNC方式</strong></p>
<p><strong>如果有绑定微软账号,那么用户名其实是你微软账号的用户名,密码同理,如果你电脑开通了PIN登录,但是你需要输入的密码还是微软账号的密码</strong></p>
<p><strong>如果我们附近没有第二台机器供我们测试,我们可以测试用虚拟机里面的机器远程连接我们本机,PRD的方式会在连接成功后的几秒显示有冲突而退出PRD,VNC方式可以套娃一直连接</strong></p>
<h2 id="window安装ultravnc">window安装UltraVNC</h2>
<p>官网下载合适的版本即可: https://uvnc.com/</p>
<p>一直next即可</p>
<p>安装之后,他会在本地启一个uvnc_service 服务</p>
<p>我们打开安装 UltraVNC Server 软件,我们底部任务栏会出现他的图标,在他的图标上右边打开Admin properties</p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220722160246843-2125382246.png" alt="" loading="lazy"></p>
<ol>
<li>VNC Password:VNC连接时的密码</li>
<li>View-Only Password:连接后只允许看的密码</li>
<li>默认VNC的连接端口</li>
</ol>
<p>更改完之后直接apply-ok即可</p>
<h2 id="集成guacamole--api">集成GuacamoleAPI</h2>
<h3 id="需要的环境">需要的环境</h3>
<p>https://guacamole.apache.org/api-documentation/</p>
<p>我们集成的话需要上面链接里面的 <code>Java (guacamole-common)</code> <code>JavaScript (guacamole-common-js)</code>两个包</p>
<ol>
<li>
<p><code>Java (guacamole-common)</code></p>
<p>这个使用maven下载即可</p>
<pre><code class="language-xml"><dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common</artifactId>
<version>1.4.0</version>
</dependency>
</code></pre>
</li>
<li>
<p><code>JavaScript (guacamole-common-js)</code></p>
<p>这个包也是有maven,但是我本机下不下来,我看其他人也有这种情况,所以此包在下文中采用下载包的形式</p>
<p>https://search.maven.org/artifact/org.apache.guacamole/guacamole-common-js/1.4.0/pom</p>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220727114304504-942174381.png" alt="" loading="lazy"></p>
<p>选择下载zip包解压,即可</p>
</li>
</ol>
<h3 id="servlet项目集成">Servlet项目集成</h3>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220727114245523-1935612849.png" alt="" loading="lazy"></p>
<ol>
<li>
<p>先新建一个Servlet项目</p>
</li>
<li>
<p>放入maven <strong>Guacamole</strong>依赖</p>
</li>
</ol>
<pre><code class="language-xml"><!-- Main Guacamole library -->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common</artifactId>
<version>1.4.0</version>
</dependency>
</code></pre>
<ol start="3">
<li>创建相应文件</li>
</ol>
<p><img src="https://img2022.cnblogs.com/blog/2153378/202207/2153378-20220727114314911-77413508.png" alt="" loading="lazy"></p>
<ul>
<li>创建<code>TutorialGuacamoleTunnelServlet</code>类</li>
<li>在webapp目录下,放入上文下载的js压缩包里面的内容(里面的js其实真正用到的只有<code>all.js</code>和<code>all.min.js</code>这两个选择一个使用即可)</li>
<li>创建<code>index.html</code>文件</li>
</ul>
<ol start="4">
<li>填充文件内容</li>
</ol>
<ul>
<li><code>TutorialGuacamoleTunnelServlet</code>文件内容:</li>
</ul>
<pre><code class="language-java">public class TutorialGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet {
@Override
protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
//此方法为http的连接方式,如果是websocker方式,请继承相关的类`GuacamoleWebSocketTunnelEndpoint`
// Create our configuration
GuacamoleConfiguration config = new GuacamoleConfiguration();
config.setProtocol("rdp");
config.setParameter("hostname", "自己测试的远程ip");
config.setParameter("port", "测试连接端口");
config.setParameter("username", "用户名");
config.setParameter("password", "密码");
config.setParameter("ignore-cert", "true");
// Connect to guacd - everything is hard-coded here.
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket("运行guacd的机器ip", 4822),
config
);
// Return a new tunnel which uses the connected socket
return new SimpleGuacamoleTunnel(socket);
}
}
</code></pre>
<ul>
<li><code>web.xml</code>文件内容</li>
</ul>
<pre><code class="language-xml"><!-- 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>
<!-- TutorialGuacamoleTunnelServlet类的具体路径,具体到类名 -->
com.example.e.类名
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>Tunnel</servlet-name>
<url-pattern>/tunnel</url-pattern>
</servlet-mapping>
</code></pre>
<ul>
<li><code>index.html</code>文件内容</li>
</ul>
<pre><code class="language-xml"><!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<script type="text/javascript"
src="guacamole-common-js/all.min.js"></script>
<!-- Display -->
<div id="display"></div>
<script type="text/javascript"> /* <![CDATA[ */
// Get display div from document
var display = document.getElementById("display");
// Instantiate client, using an HTTP tunnel for communications.
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>
</code></pre>
<ol start="5">
<li>启动创建项目时配置的tomcat服务,打开tomcat服务配置里面的url,如果连接参数配置正确,此时就可以看到了</li>
</ol>
<h3 id="springboot--vue-项目集成">springboot + vue 项目集成</h3>
<p>springboot + vue项目请自行创建</p>
<ol>
<li>配置maven</li>
</ol>
<pre><code class="language-xml"><!-- 远程控制-->
<dependency>
<groupId>org.apache.guacamole</groupId>
<artifactId>guacamole-common</artifactId>
<version>1.4.0</version>
</dependency>
<!-- 添加servlet支持-->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
</code></pre>
<p>因为api依赖servlet的支持,所以需要额外添加servlet的包,Servlet集成的时候,新建项目自带这个包</p>
<ol start="2">
<li>创建<code>TutorialGuacamoleTunnelServlet</code>类,放入合适的包中即可</li>
</ol>
<pre><code class="language-java">//配置请求路径 /tunnel
@WebServlet(name = "Tunnel", urlPatterns = "/tunnel")
public class TutorialGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet {
@Override
protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
GuacamoleConfiguration config = new GuacamoleConfiguration();
//config.setProtocol("vnc");
//根据header参数来进行参数化
config.setProtocol(request.getHeader("loginType"));
config.setParameter("hostname", request.getHeader("hostName"));
config.setParameter("port", request.getHeader("port"));
config.setParameter("username", request.getHeader("userName"));
config.setParameter("password", request.getHeader("password"));
config.setParameter("ignore-cert", request.getHeader("ignore"));
GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
new InetGuacamoleSocket("192.168.150.128", 4822),
config
);
return new SimpleGuacamoleTunnel(socket);
}
}
</code></pre>
<ol start="3">
<li>在springboot的启动类里面加上注解</li>
</ol>
<pre><code class="language-java">//扫描这个目录下的servlet,这个不需要具体到类名,到包名即可
@ServletComponentScan("com.framework.servlet")
</code></pre>
<ol start="4">
<li>解除此url的访问后端接口权限(非必要步骤,可省略)因为集成在真实的项目里,而我们项目用的是<code>spring security</code>所以需要对这个url进行解除访问限制</li>
</ol>
<pre><code class="language-java">//只允许登录用户访问,这个地方需要这个接口认证token,然后认证token,后面会讲
.antMatchers("/tunnel/**").authenticated()
//允许任何人访问
.antMatchers("/tunnel/**").permitAll()
这两个选一个即可
</code></pre>
<ol start="5">
<li>前端新建路由配置</li>
</ol>
<pre><code class="language-js">{
path: "/remote-page",
//比如我准备展示远程桌面的页面放入了这个路径下面
component: () => import("@/views/business/tunnel/index"),
},
</code></pre>
<ol start="6">
<li>请自行在相应的目录下新建页面</li>
<li>我这里的逻辑是一个页面有一个登录按钮点击打开新页面,这个新页面就是展示远程桌面的页面,为此打开新页面的页面逻辑如下</li>
</ol>
<pre><code class="language-js">//配置内容请自行填写
const loginForm = {
hostName: "0.0.0.0"
ignore: "true"
loginType: "rdp"
password: "123"
port: "3389"
userName: "pass"
}
let openUrl = window.location.origin + "/remote-page?";
for (const of Object.entries(loginForm)) {
openUrl += "&" + key + "=" + value;
}
window.open(openUrl, "_blank");
</code></pre>
<ol start="8">
<li>展示远程桌面的文件内容</li>
</ol>
<pre><code class="language-js"><template>
<div>
<!-- Display -->
<div id="display"></div>
</div>
</template>
<script>
//如果你后端配置的是需要token认证的,请使用你们项目里面自己带的获取token的方法
import { getToken } from "@/utils/auth";
export default {
data() {
return {
params: {},
};
},
mounted() {
this.initUrlParams();
this.initGuacamole();
},
methods: {
// 初始化url
initUrlParams() {
this.params = this.getQueryObject(window.location.href);
//添加token认证
this.params["Authorization"] = "Bearer " + getToken();
},
// 初始化视频
initGuacamole() {
var display = document.getElementById("display");
var guac = new Guacamole.Client(
new Guacamole.HTTPTunnel("tunnel", true, this.params)
);
display.appendChild(guac.getDisplay().getElement());
guac.onerror = (error) => {
if (error.code === 519) {
this.$message.error(
"连接失败,请检查连接参数,10秒后自动关闭本页面!"
);
setTimeout(() => {
window.close();
}, 10000);
} else {
this.$message.error(error);
}
};
guac.connect();
window.onunload = function () {
guac.disconnect();
};
var mouse = new Guacamole.Mouse(guac.getDisplay().getElement());
mouse.onmousedown =
mouse.onmouseup =
mouse.onmousemove =
function (mouseState) {
guac.sendMouseState(mouseState);
};
var keyboard = new Guacamole.Keyboard(document);
keyboard.onkeydown = function (keysym) {
guac.sendKeyEvent(1, keysym);
};
keyboard.onkeyup = function (keysym) {
guac.sendKeyEvent(0, keysym);
};
},
//解析url参数
getQueryObject(url){
url = url == null ? window.location.href : url
const search = url.substring(url.lastIndexOf('?') + 1)
const obj = {}
const reg = /([^?&=]+)=([^?&=]*)/g
search.replace(reg, (rs, $1, $2) => {
const name = decodeURIComponent($1)
let val = decodeURIComponent($2)
val = String(val)
obj = val
return rs
})
return obj
}
},
};
</script>
<style lang="scss" scoped></style>
</code></pre>
<ol start="9">
<li>引入<code>guacamole-common-js</code></li>
</ol>
<p>原包使用import导入的话会提示找不到<strong>Guacamole</strong>对象,所以我更改了下源码,<strong>建议大家先不改,先试试好不好报错,再来决定需要不需要改</strong></p>
<p>这里我使用的是<code>all.js</code>把里面的第一行代码</p>
<pre><code class="language-js">var Guacamole = Guacamole || {};
=>
window.Guacamole = Guacamole || {};
</code></pre>
<p>在<code>main.js</code>里面引入</p>
<pre><code class="language-js">//请自行更改路径
import "@/utils/guacamole-common-js/all.js";
</code></pre>
<p>如果你不想更改源码并且也报错的话,那么可以直接放在public目录下,然后在index.html里面引入</p>
<pre><code><script src="<%= BASE_URL %>all.js"></script>
</code></pre>
<ol start="10">
<li>现在已经可以启动查看了,这中间的步骤如果大家有错误可能确实是我没想起来,没有写上,但是这些步骤已经足够精简了</li>
</ol><br><br>
来源:https://www.cnblogs.com/wwy-gongqr/p/16506105.html
頁:
[1]