【问题标题】:Jetty Java websocket client doesn't connect to serverJetty Java websocket客户端未连接到服务器
【发布时间】:2016-08-22 21:25:15
【问题描述】:

我正在使用编写的 Java Jetty 客户端 [websocket-client 9.3.8.RC0]。在我们的例子中,Websocket 服务器有点奇怪。 它接受格式的请求。 wss://192.168.122.1:8443/status?-xsrf-=tokenValue

在第一个登录 POST 请求中收到令牌值,在该请求中我得到令牌值和 Cookie 标头。 Cookie 作为标头添加,而令牌作为参数给出。 现在的问题是: - 当我在下面运行代码时,它只是在启动时调用 awaitclose() 函数。但是没有调用其他函数,即 Onconnected 甚至 Onclose。

任何帮助都可以进一步调试它,查看任何日志或环境问题以了解 Socket 未连接的原因。

试图找出以下几点进行调试。 1. 检查客户端证书是否导致问题。

用我的 python 代码 wspy.py 试过了,它工作得很好。

代码是

public final class websocketxxx {

WebSocketClient client=null;
public websocketxxx (){

}


public void run(String host,String cookieVal, String xsrfVal, String resource) throws IOException {

    SslContextFactory sslContextFactory = new SslContextFactory();
    sslContextFactory.setTrustAll(true);
    WebSocketClient client = new WebSocketClient(sslContextFactory);
    MyWebSocket socket = new MyWebSocket();
    try {
        client.start();
        ClientUpgradeRequest request = new ClientUpgradeRequest();
        // Add the authentication and protocol to the request header
        // Crate wss URI from host and resource
        resource = resource + xsrfVal;
        URI destinationUri = new URI("wss://" + host + resource); // set URI
        request.setHeader("cookie",cookieVal);
        request.setHeader("Sec-WebSocket-Protocol", "ao-json");
        //System.out.println("Request Headers print : "  request.getHeaders())
        System.out.println("Connecting to : " + destinationUri);
        client.connect(socket, destinationUri, request);
        socket.awaitClose(5000, TimeUnit.SECONDS);
    } catch (Throwable t) {
        t.printStackTrace();
    } finally {
        try {
            client.stop();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
@WebSocket
public class MyWebSocket {
    private final CountDownLatch closeLatch = new CountDownLatch(1);

    @OnWebSocketConnect
    public void onConnect(Session session) {
        System.out.println("WebSocket Opened in client side");
        try {
            System.out.println("Sending message: Hi server");
            session.getRemote().sendString("Hi Server");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @OnWebSocketMessage
    public void onMessage(String message) {
        System.out.println("Message from Server: " + message);
    }

    @OnWebSocketClose
    public void onClose(int statusCode, String reason) {
        System.out.println("WebSocket Closed. Code:" + statusCode);
    }

    public boolean awaitClose(int duration, TimeUnit unit) throws InterruptedException {
        return this.closeLatch.await(duration, unit);
    }
}

public Client getBypassCertVerificationClient() {
    Client client1 = null;
    try {
        // Create a HostnameVerifier that overrides the verify method to accept all hosts
        HostnameVerifier hostnameVerifier = new HostnameVerifier() {
            public boolean verify(String host, SSLSession sslSession) {
                return true;
            }
        };
        // Create a TrustManager
        TrustManager[] trust_mgr = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(X509Certificate[] certs, String t) {
                    }
                    public void checkServerTrusted(X509Certificate[] certs, String t) {
                    }
                }
        };
        // Create the SSL Context
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, trust_mgr, new SecureRandom());
        // Create the client with the new hostname verifier and SSL context
        client1 = ClientBuilder.newBuilder()
                .sslContext(sslContext)
                .hostnameVerifier(hostnameVerifier)
                .build();
    } catch (NoSuchAlgorithmException e) {
        e.printStackTrace();
    } catch (KeyManagementException e) {
        e.printStackTrace();
    }
    return client1;
}

public String[] simple_Login_POST_request(String host, String user, String password, String resource, String data) {
    String resp = null;
    String[] headers = new String[2];

    try {
        // Create a Client instance that supports self-signed SSL certificates
        Client client = getBypassCertVerificationClient();

        // Create a WebTarget instance with host and resource
        WebTarget target = client.target("https://" + host).path(resource);

        // Build HTTP request invocation
        Invocation.Builder invocationBuilder = target.request();

        // Encode the user/password and add it to the request header
        invocationBuilder.header(HttpHeaders.CONTENT_TYPE, "application/x-www-form-urlencoded");
        Form form = new Form();
        form.param("userid", user);
        form.param("password", password);
        // Invoke POST request and get response as String
        //post(Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE));

        Response response = invocationBuilder.method("POST", Entity.entity(form,MediaType.APPLICATION_FORM_URLENCODED_TYPE));
        resp = (String) response.readEntity(String.class);

        // Print input URL, input data, response code and response
        System.out.println("URL: [POST] " + target.getUri().toString());
        System.out.println("HTTP Status: " + response.getStatus());
        System.out.println("HTTP Status: " + response.getHeaders());
        headers[0] = response.getHeaderString("Set-Cookie");
        //response.getStringHeaders()
        headers[1] = response.getHeaderString("X-XSRF-TOKEN");
        System.out.println("Response: \n" + resp);

        response.close();
    } catch (Exception e) {
        e.printStackTrace();
    }
    return headers;
}



public static void main(String[] args) throws IOException {
    String host = "";
    String user = "";
    String password = "";
    String resource = "";

    host ="192.168.122.1:8443";
    user = "ADMIN";
    password ="ADMIN";
    websocketXXX wsNotification = new websocketxxx();
    /////////////////////////////////////////////////////////////////
    // Simple POST LOGIN Request 
    resource = "/api/login";
    String headers[]=  wsNotification.simple_Login_POST_request(host, user, password, resource, null);
    ////////////////////////////////////////////////////////////////
    headers[0] = headers[0].substring(headers[0].lastIndexOf(",") + 1);
    System.out.println("headers[0]: " + headers[0] + "\n");
    String cookie = headers[0];
    String XSRFToken = headers[1];

    resource = "/status?-xsrf-=";
    //wsNotification.simple_websocket_example(host, cookie, XSRFToken, resource);
    wsNotification.run(host, cookie, XSRFToken, resource);

}
}

【问题讨论】:

    标签: eclipse websocket jetty


    【解决方案1】:

    实现大部分是正确的。

    设置原始CookieSec-WebSocket-* 标头is forbidden,您必须使用API​​。

    Cookie 处理来自:

    ClientUpgradeRequest request = new ClientUpgradeRequest();
    request.setHeader("cookie",cookieVal);
    

    ClientUpgradeRequest.setCookies()

    ClientUpgradeRequest request = new ClientUpgradeRequest();
    List<HttpCookie> cookies = new ArrayList<>();
    cookies.add(new HttpCookie(...));
    request.setCookies(cookies);
    

    注意:如果您使用的是 java CookieStore,那么您也可以使用 setCookiesFrom(CookieStore) 方法将 CookieStore 实例传递给客户端。

    子协议选择来自:

    ClientUpgradeRequest request = new ClientUpgradeRequest();
    request.setHeader("Sec-WebSocket-Protocol", "ao-json");
    

    ClientUpgradeRequest.setSubProtocols()

    ClientUpgradeRequest request = new ClientUpgradeRequest();
    request.setSubProtocols("ao-json");
    

    【讨论】:

    • 根据您的更改尝试了以下代码,但没有任何帮助。没有调用 onConnected() 方法。这是更改的 sn-p **************************URI destinationUri = new URI("wss://" + host + resource) ; // 设置 URI List cookies = new ArrayList(); cookies.add(new HttpCookie("Cookie", cookieVal)); request.setCookies(cookies); request.setSubProtocols("ao-json"); System.out.println("正在连接:" + destinationUri); client.connect(socket, destinationUri, request);
    • 添加@OnWebSocketError 处理程序,看看您是否收到通过websocket 层报告的某种错误。
    • 现在的问题是 cookie 头 下面是删除十六进制代码后的 SSH 握手打印:no-cache..Sec-WebSocket-Protocol:ao-json Cookie:Cookie="-http-session-=4 ::http.session::78c7ec010a4845e5457c91546e91c3; path=/; secure; httponly"... 看到这个 Cookie 标头它绝对是错误的。现在正在尝试纠正它
    • 正确使用 java.net.HttpCookie API,不要把你的 cookieVal 塞进去而不考虑 Cookie 的值是什么。
    • @JoakimErdfelt 您添加错误处理程序的提示确实应该是答案之一,而不是评论。这确实帮助我解决了一个类似的问题(我的 websocket 端点返回了 400,它不会显示在错误处理程序中的其他任何地方)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-27
    • 1970-01-01
    • 1970-01-01
    • 2020-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多