You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Guacamole WebSocket隧道?Java端实现及Token获取疑问

Guacamole WebSocket隧道实现与认证问题解答

现有Guacamole最简HTTP隧道实现代码(如下),因低延迟需求希望改用WebSocket隧道,存在以下疑问:

  1. 如何在Java端实现WebSocket隧道?
  2. GuacamoleHTTPTunnelServlet类是否会在调用JavaScript的WebsocketTunnel函数时自动处理WebSocket升级?
  3. 使用Guacamole.WebSocketTunnel函数时要求URL携带认证token,但目前无法获取该token,求解决方案或思路。

HTTP隧道实现代码:

package org.apache.guacamole.net.example;

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

public class TutorialGuacamoleTunnelServlet
    extends GuacamoleHTTPTunnelServlet {

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

        // Create our configuration
        GuacamoleConfiguration config = new GuacamoleConfiguration();
        config.setProtocol("vnc");
        config.setParameter("hostname", "localhost");
        config.setParameter("port", "5901");
        config.setParameter("password", "potato");

        // Connect to guacd - everything is hard-coded here.
        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket("localhost", 4822),
                config
        );

        // Return a new tunnel which uses the connected socket
        return new SimpleGuacamoleTunnel(socket);;

    }

}

前端调用WebSocket隧道示例代码:

let tunnel = new Guacamole.WebSocketTunnel(`/websocket-tunnel?token=${token}`);

解答

1. Java端实现WebSocket隧道的方式

无需修改核心连接逻辑,只需将继承的父类从GuacamoleHTTPTunnelServlet改为GuacamoleWebSocketTunnelServlet,它是Guacamole专门用于处理WebSocket隧道请求的Servlet类。示例代码如下:

package org.apache.guacamole.net.example;

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

public class TutorialGuacamoleWebSocketTunnelServlet
    extends GuacamoleWebSocketTunnelServlet {

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

        // 复用原有配置逻辑
        GuacamoleConfiguration config = new GuacamoleConfiguration();
        config.setProtocol("vnc");
        config.setParameter("hostname", "localhost");
        config.setParameter("port", "5901");
        config.setParameter("password", "potato");

        // 连接guacd服务
        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket("localhost", 4822),
                config
        );

        return new SimpleGuacamoleTunnel(socket);
    }

}

同时需要在web.xml或通过Servlet 3.0+注解配置该Servlet的映射路径:

<servlet>
    <servlet-name>WebSocketTunnelServlet</servlet-name>
    <servlet-class>org.apache.guacamole.net.example.TutorialGuacamoleWebSocketTunnelServlet</servlet-class>
</servlet>
<servlet-mapping>
    <servlet-name>WebSocketTunnelServlet</servlet-name>
    <url-pattern>/websocket-tunnel</url-pattern>
</servlet-mapping>

2. GuacamoleHTTPTunnelServlet不支持WebSocket升级

GuacamoleHTTPTunnelServlet仅处理基于HTTP的隧道请求(如长连接、轮询),没有实现WebSocket的握手和升级逻辑。必须使用GuacamoleWebSocketTunnelServlet来处理WebSocket类型的隧道连接请求。

3. 认证token的解决方案

Guacamole要求WebSocket隧道携带token是为了验证请求合法性,避免未授权连接,常见实现思路有两种:

方案一:自定义token生成与验证逻辑

  • 生成token:用户登录或初始化连接时,后端生成唯一标识(如UUID),将该token与用户的连接配置(如VNC主机、端口、密码)绑定,存储在缓存(如Redis、内存Map)中,并设置过期时间。
  • 前端获取token:通过后端接口拿到生成的token,拼接在WebSocket请求URL中。
  • 验证token:在GuacamoleWebSocketTunnelServlet的doConnect方法中,从请求参数提取token,验证其有效性并取出对应配置:
    @Override
    protected GuacamoleTunnel doConnect(HttpServletRequest request) throws GuacamoleException {
        String token = request.getParameter("token");
        // 验证token有效性,从缓存中获取对应配置
        GuacamoleConfiguration config = validateToken(token);
        if (config == null) {
            throw new GuacamoleException("无效或过期的token");
        }
        // 后续连接guacd的逻辑不变
        GuacamoleSocket socket = new ConfiguredGuacamoleSocket(
                new InetGuacamoleSocket("localhost", 4822),
                config
        );
        return new SimpleGuacamoleTunnel(socket);
    }
    

方案二:复用Guacamole内置认证机制

如果使用Guacamole官方认证扩展(如数据库、LDAP认证),可以直接调用Guacamole的API生成合法token:

  • 后端通过TokenAuthenticationProvider或相关接口,传入用户凭证生成符合Guacamole规范的token。
  • 前端通过接口获取该token后发起WebSocket连接,无需自定义验证逻辑,直接复用Guacamole的权限体系。

内容的提问来源于stack exchange,提问作者Groggy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 19:24:53