Apache Guacamole集成到spring boot、vue

一、创建spring项目

引入依赖

 <!-- Main Guacamole library -->
        <dependency>
            <groupId>org.apache.guacamole</groupId>
            <artifactId>guacamole-common</artifactId>
            <version>1.5.2</version>
            <scope>compile</scope>
        </dependency>

        <!-- Guacamole JavaScript library -->
        <dependency>
            <groupId>org.apache.guacamole</groupId>
            <artifactId>guacamole-common-js</artifactId>
            <version>1.5.2</version>
            <type>zip</type>
            <scope>runtime</scope>
        </dependency>

二、创建http服务处理



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.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;

/**
 * @author 
 * @program 
 * @description http远程桌面请求
 * @packagename 
 * @date 2023-06-07 16:51
 **/
@WebServlet(urlPatterns = "/tunnel")
public class TutorialGuacamoleTunnelServlet extends GuacamoleHTTPTunnelServlet {
    /**
     *
     */
    private static final long serialVersionUID = -3224942386695394818L;

    @Override
    protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {

        //guacamole server地址
        String hostname = "";
        //guacamole server端口
        int port = 4822;
        GuacamoleConfiguration configuration = new GuacamoleConfiguration();
        // 远程连接协议
        configuration.setProtocol("rdp");
        configuration.setParameter("hostname", "");
        configuration.setParameter("port", "3389");
        configuration.setParameter("username", "");
        configuration.setParameter("password", "");
        configuration.setParameter("ignore-cert", "true");

        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket(hostname, port),
                configuration
        );
        GuacamoleTunnel tunnel = new SimpleGuacamoleTunnel(socket);
        return tunnel;
    }
}

三、将guacamole-common-js压缩包解压复制到vue,guacamole-common-js压缩包在依赖下载路径下找

在vue的index.html同目录下创建static目录 将解压的guacamole-common-js目录复制到该目录下

四、显示远程界面

<!--
 * @Descripttion: 远程桌面
 * @Author: 
 * @Date: 
 * @LastEditors: 
 * @LastEditTime: 
-->
<template>
  <div
    class="remote-desktop"
    style="height: calc(100vh - 130px); margin: 0px 16px 8px; overflow-x: auto"
  >
    <div id="display"></div>
  </div>
</template>
<script>
export default {
  props: {},
  data() {
    return {};
  },
  mounted: function () {
    this.$nextTick(function () {
      this.show();
    });
  },
  methods: {
    // 失活页面时
    deactivated() {},
    // 激活页面时
    activated() {},
    show() {
      // Get display div from document
      var display = document.getElementById("display");

      // Instantiate client, using an HTTP tunnel for communications.
      // tunnel
      //访问地址  这里我做了转发 请按自己服务填写 如 http://192.168.6.14:8080/tunnel
      var guac = new Guacamole.Client(
        new Guacamole.HTTPTunnel("/guacamole/tunnel")
      );
      // Add client to display div
      display.appendChild(guac.getDisplay().getElement());

      // Error handler
      guac.onerror = function (error) {
        console.log(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>

 <style>
#display{
  z-index:999 ;
  position: absolute;
}
</style>

五、http协议会导致一直有请求,建议使用webSocket。修改如下

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.GuacamoleClientInformation;
import org.apache.guacamole.protocol.GuacamoleConfiguration;
import org.apache.guacamole.websocket.GuacamoleWebSocketTunnelEndpoint;
import org.springframework.stereotype.Component;

import javax.websocket.EndpointConfig;
import javax.websocket.Session;
import javax.websocket.server.ServerEndpoint;

/**
 * @author 
 * @program 
 * @description WebSocket远程桌面请求
 * @packagename 
 * @date 2023-06-08 09:18
 **/
@ServerEndpoint(value = "/webSocket", subprotocols = "guacamole")
@Component
public  class WebSocketTunnel extends GuacamoleWebSocketTunnelEndpoint {

    private static String host;
    private static int port;

    @Value("${guacamole.host:127.0.0.1}")
    public void setHost(String host) {
        WebSocketTunnel.host = host;
    }

    @Value("${guacamole.port:4822}")
    public void setPort(int port) {
        WebSocketTunnel.port = port;
    }
    /**
     * 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 {
        System.out.println("sessionMap:" + session.getRequestParameterMap());
        // 获取url的值
        Integer height = Integer.valueOf(session.getRequestParameterMap().get("height").get(0));
        Integer width = Integer.valueOf(session.getRequestParameterMap().get("width").get(0));
        GuacamoleClientInformation information = new GuacamoleClientInformation();
        information.setOptimalScreenHeight(height);
        information.setOptimalScreenWidth(width);

        //--------------------------windows远程桌面测试--------------------------
        GuacamoleConfiguration configuration = new GuacamoleConfiguration();
        configuration.setProtocol("rdp");
        configuration.setParameter("hostname", "");
        configuration.setParameter("port", "3389");
        configuration.setParameter("username", "");
        configuration.setParameter("password", "123456");
        //忽略证书
        configuration.setParameter("ignore-cert", "true");

        //domain 域
        //security 安全模式 any-任意  nla-网络级别认证  nla-ext-扩展网络级身份验证  tls-TLS加密  vmconnect-Hyper-V / VMConnect  rdp-RDP加密
        //disable-auth 禁用认证 true false
        //显示设置
        //color-depth 色彩深度 8-256色 16-低色(16位) 24-真彩(24位) 32-真彩(32位)
        //width 宽
        //height 高
        //dpi 分辨率
        //resize-method 缩放方法 display-update-显示更新  reconnect-重新连接
        //read-only 只读 true false

        //vnc 参考地址https://guacamole.apache.org/doc/gug/configuring-guacamole.html#vnc
        //autoretry 在放弃并返回错误之前重试连接的次数
        //显示设置
        //color-depth 色彩深度 8-256色 16-低色(16位) 24-真彩(24位) 32-真彩(32位)
        //swap-red-blue 交换红/蓝成分 true false
        //cursor 光标 local-本地 remote-远程
        //read-only 只读 true false
        //force-lossless true false
        //代理设置
        //dest-host
        //dest-port

        //--------------------------windows远程桌面测试--------------------------

        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket(host, port),
                configuration,
                information
        );

        GuacamoleTunnel tunnel = new SimpleGuacamoleTunnel(socket);
        return tunnel;
    }
}
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.socket.server.standard.ServerEndpointExporter;

/**
 * @author 
 * @program 
 * @description
 * @packagename 
 * @date 2023-06-08 18:01
 **/
@Configuration
public class WebSocketConfig {

    @Bean
    public ServerEndpointExporter serverEndpointExporter(){
        return new ServerEndpointExporter();
    }
}

vue修改如下

// Instantiate client, using an HTTP tunnel for communications.
      // tunnel
      // Instantiate client, using an HTTP tunnel for communications.
      // tunnel
      //访问地址  这里我做了转发 请按自己服务填写 如 http://192.168.6.14:8080/tunnel
      //var guac = new Guacamole.Client(
       // new Guacamole.HTTPTunnel("/guacamole/tunnel")
      //);
       var guac = new Guacamole.Client(
                new Guacamole.WebSocketTunnel("ws://192.168.6.14:8088/guacamole/webSocket")
             );
     // 如果需要传参 在连接出编写
      guac.connect("height=" +
            display.clientHeight +
            "&width=" +
            display.clientWidth +
            "&id=" +
            this.record.id);

整体代码

<!--
 * @Descripttion: 远程桌面
 * @Author: 
 * @Date: 
 * @LastEditors: 
 * @LastEditTime: 
-->
<template>
  <div
    class="remote-desktop"
    style="height: calc(100vh - 130px); margin: 0px 16px 8px; overflow-x: auto"
  >
    <BasicBreadcrumb :data="breadcrumbData" @click="cancel" @back="cancel" />
    <div
      id="display"
      style="height: calc(-194px + 100vh); width: calc(-280px + 100vw)"
    >
      <a-result status="warning" :title="resultTitle" v-if="showResult">
        <template #extra>
          <a-button key="console" type="primary" @click="cancel">
            返回
          </a-button>
        </template>
      </a-result>
    </div>
  </div>
</template>
<script>
export default {
  props: {
    menu: {},
    btnItem: {},
    record: {},
  },
  data() {
    return {
      guac: null,
      showResult: false,
      keyboard: null,
      resultTitle: "",
      breadcrumbData: [],
    };
  },
  mounted: function () {
    this.$nextTick(function () {
      this.show();
    });
  },
  destroyed: function () {
    this.guac.disconnect();
    this.keyboard.onkeydown = null;
    this.keyboard.onkeyup = null;
  },
  methods: {
    // 失活页面时
    deactivated() {
      if (this.keyboard != null) {
        this.keyboard.onkeydown = null;
        this.keyboard.onkeyup = null;
      }
    },
    // 激活页面时
    activated() {
      var _this = this;
      if (_this.keyboard != null) {
        _this.keyboard.onkeydown = function (keysym) {
          _this.guac.sendKeyEvent(1, keysym);
        };

        _this.keyboard.onkeyup = function (keysym) {
          _this.guac.sendKeyEvent(0, keysym);
        };
      }
    },
    cancel() {
      this.$emit("cancel");
    },
    show() {
      // Get display div from document
      var display = document.getElementById("display");
      var _this = this;
      // Instantiate client, using an HTTP tunnel for communications.
      // tunnel
      // 192.168.6.14:8080/tunnel
      //var guac = new Guacamole.Client(
      //new Guacamole.HTTPTunnel("/guacamole/tunnel")
      //);
      this.guac = new Guacamole.Client(
        new Guacamole.WebSocketTunnel(
          "/guacamole/webSocket"
        )
      );
      // Add client to display div
      display.appendChild(this.guac.getDisplay().getElement());

      // Error handler message
      this.guac.onerror = function (error) {
        console.log(error);
        _this.resultTitle = error.message;
        _this.showResult = true;
      };

      // Connect
      this.guac.connect("height=" +
            display.clientHeight +
            "&width=" +
            display.clientWidth +
            "&id=" +
            this.record.id);

      // Disconnect on close
      window.onunload = function () {
        _this.guac.disconnect();
      };

      this.guac.onstatechange = function (state) {
        console.log(state);
        if (state == 3) {
          // Mouse
          var mouse = new Guacamole.Mouse(_this.guac.getDisplay().getElement());

          mouse.onmousedown =
            mouse.onmouseup =
            mouse.onmousemove =
              function (mouseState) {
                _this.guac.sendMouseState(mouseState);
              };

          // Keyboard
          _this.keyboard = new Guacamole.Keyboard(document);

          _this.keyboard.onkeydown = function (keysym) {
            _this.guac.sendKeyEvent(1, keysym);
          };

          _this.keyboard.onkeyup = function (keysym) {
            _this.guac.sendKeyEvent(0, keysym);
          };
        }
      };
    },
  },
};
</script>

 <style>
#display {
  z-index: 999;
  position: absolute;
}
</style>

连接vnc时 vnc服务修改配置 不然连接不上 原因未知

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值