WebSocket HTTPS connection

See now how start a WebSocket secure connection with a java client. First, create a WebSocket endpoint:

@ServerEndpoint(value = "/session") 
public class SessionSocketServer {
...

@OnOpen
public
void onOpen(Session session) throws NamingException {
...
}
@OnMessage
public
String onMessage(String message, Session session) {
return "Server received [" + message + "]";
}
@OnClose
public
void onClose(Session session) {
...
}
@OnError
public
void onError(Throwable exception, Session session) {
...
}
}

And a basic WebSocket client:

public class SecureSocketClient extends Endpoint {
...
private static final BlockingDeque<String> queue = new LinkedBlockingDeque<>();

@Override
public void onClose(final Session session, CloseReason closeReason) {
}
public static void awake() throws InterruptedException {
queue.poll(5, SECONDS);
}
@Override
public void onOpen(Session session, EndpointConfig config) {
...
session.getAsyncRemote().sendText("hi");
}
}

This client is different from the previous client we have seen in the paragraph of WebSocket container, because in the first example we have used the annotations. The Java WebSocket specifications provide interfaces too as an alternative. In this case, the interface javax.websocket.Endpoint is used instead of the javax.websocket.ClientEndpoint annotation.

Undertow, by default, lets us navigate in the enterprise components in both modes, HTTP and HTTPS. If we want to force the server WebSocket endpoint to work only in HTTPS, we must configure the web.xml file of the application. This file is the standard descriptor for web applications. Here is a sample to force the transport as confidential to all HTTP URL contexts starting with the work session. Confidential transport is used to guarantee an encrypted channel. Here is the code of the web.xml descriptor file:

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<security-constraint>
<web-resource-collection>
<web-resource-name>Secure WebSocket</web-resource-name>
<url-pattern>/session</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
...
</web-app>

This configuration allows automatic redirect to a HTTPS connection, even if we run an HTTP call.

To start the HTTPS connection, as the first thing, we need to import an SSL context:

private SSLContext createSSLContext() throws Exception {
SSLContext sslContext = getInstance("TLS");
TrustManager tm = new X509TrustManager() {
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
}
public X509Certificate[] getAcceptedIssuers() {
return null;
}
};
sslContext.init(null, new TrustManager[] { tm }, null);
return sslContext;
}
...
SSLContext context = createSSLContext();
...

The SSL context is available from Java standard since the 1.4 version through the javax.net.ssl.SSLContext class. Because our X.509 certificate is not verified, we must force the trust manager to accept the connection. To do it, we can simply write a new X509TrustManager with empty methods and configure it in the init method of our SSL context.

The same thing is done when we connect to an uncertified site and the browser asks us to connect in anyway though we know its low reliability the possible security problems. In this image, we can see what happens when we connect with to the WildFly default page in HTTPS:

Once we have the SSL context, we can start the connection to the endpoint through our Java WebSocket client:

SecureSocketClient endpoint = new SecureSocketClient();
ClientEndpointConfig clientEndpointConfig = create().build();
clientEndpointConfig.getUserProperties().put(SSL_CONTEXT, context);
final WebSocketContainer serverContainer = getWebSocketContainer();
URI uri = new URI("wss://127.0.0.1:8443/secure-test/session");
serverContainer.connectToServer(endpoint, clientEndpointConfig, uri);

Another WebSocket component joint to the code is javax.websocket.ClientEndpointConfig. It provides a custom configuration for the client. To establish the SSL connection, we must add the SSL context to the user properties of the client. Note the used protocol for the WebSocket. WSS, WebSocket secure, is the secure protocol to use for the HTTPS connections.

8443 is the default SSL port configured in WildFly for the web application. We can customize it in the standalone.xml file:

 <socket-binding name="https" port="${jboss.https.port:8443}"/>

Or simply add a Java property when we start WildFly. Here is a sample:

./standalone.sh -Djboss.https.port=8444

We can verify the HTTPS connection inside the SessionSocketServer instance:

private Logger logger = getLogger(SessionSocketServer.class.getName());
...
@OnOpen
public void onOpen(Session session) throws NamingException {
logger.info("session secure: "+session.isSecure());
}

The result of the connection will be true.

Using JavaScript, the connection happens in a simpler manner because the SSL context is managed by the browser. So our JavaScript code will be something similar:

var ws = new WebSocket("wss://127.0.0.1:8443/secure-test/session");
ws.onopen = function() {
alert("Web Socket is connected!!");
};
...
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.116.8.110