Reputation: 113
I have a web service that runs on Tomcat and decided to try using Undertow instead. Generally, it's quite good, but I need HTTPS support and cannot enable it. Here is some helloworld code:
DeploymentInfo servletBuilder = deployment()
.setClassLoader(ServletServer.class.getClassLoader())
.setContextPath("/")
.setDeploymentName("AuthenticationService.war")
.addServlet(servlet("WSServlet", WSServlet.class))
.addListener(listener(WSServletContextListener.class))
.setResourceManager(new FileResourceManager(new File("src/main/webapp"), 100));
DeploymentManager manager = defaultContainer().addDeployment(servletBuilder);
manager.deploy();
HttpHandler servletHandler = manager.start();
SSLContext context = createSSLContext(loadKeyStore("server-keystore.jsk"), loadKeyStore("server-truststore.jks"));
PathHandler path = Handlers.path(servletHandler);
Undertow server = Undertow.builder()
.addHttpsListener(8443, "localhost", context)
.setHandler(path)
.build();
server.start();
And the createSSLContext method:
private static SSLContext createSSLContext(final KeyStore keyStore, final KeyStore trustStore) throws Exception {
KeyManager[] keyManagers;
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, /* password */);
keyManagers = keyManagerFactory.getKeyManagers();
TrustManager[] trustManagers;
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext;
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
return sslContext;
}
And loadKeyStore method:
private static KeyStore loadKeyStore(String name) throws Exception {
final InputStream stream = new FileInputStream(name);
try(InputStream is = stream) {
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(is, /* password */);
return loadedKeystore;
}
}
The server is starting, but trying to send requests to https://localhost:8443/... has no effect, no logs or exceptions or some reaction. When using http://localhost:8443 it throws exception
javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
I am new to all web technologies, so all that may be strange. So what's wrong here?
Upvotes: 0
Views: 1461
Reputation: 2301
I have it working. First generate your keys if you've not done so already:
#!/usr/bin/env bash
KEYSTORE=my-keystore.jks
TRUSTSTORE=my-truststore.ts
CERT=my-client.cer
rm $KEYSTORE
rm $CERT
rm $TRUSTSTORE
# these passwords must be copied to the private config file(s)
KEYSTORE_STOREPASS=password1
KEYSTORE_KEYPASS=password2
TRUSTSTORE_STOREPASS=password3
keytool -genkey -alias pomochatserver \
-keyalg RSA -keystore $KEYSTORE \
-dname "cn=localhost, ou=IT, o=Continuent, c=US" \
-storepass $KEYSTORE_STOREPASS -keypass $KEYSTORE_KEYPASS
# enter the *KEYSTORE_STOREPASS* when prompted
keytool -export -alias pomochatserver -file $CERT -keystore $KEYSTORE
keytool -import -trustcacerts -alias pomochatserver -file $CERT \
-keystore $TRUSTSTORE -storepass $TRUSTSTORE_STOREPASS -noprompt
... then in your java code:
public static SSLContext serverSslContext(String password1, String password2, String password3) {
try {
KeyStore keyStore = loadKeyStore("my-keystore.jks", password1);
KeyStore trustStore = loadKeyStore("my-truststore.ts", password3);
return createSSLContext(keyStore, trustStore, password2);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static SSLContext createSSLContext(final KeyStore keyStore, final KeyStore trustStore, String keyStorePassword) throws IOException {
try {
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
return sslContext;
} catch (Exception e) {
throw new IOException("Unable to create and initialise the SSLContext", e);
}
}
private static KeyStore loadKeyStore(final String name, String password) throws IOException {
try(InputStream stream = new FileInputStream(name)) {
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(stream, password.toCharArray());
return loadedKeystore;
} catch (Exception e) {
throw new IOException(String.format("Unable to load KeyStore %s", name), e);
}
}
and finally to create the server
Undertow webAppServer = Undertow.builder()
.addHttpsListener(
port,
hostname,
serverSslContext(password1, password2, password3)
)
.setHandler(handlers, manager.start()))
.build();
Upvotes: 2
Reputation: 92
I'm not sure, but the self-signed and/or not trusted certificates would cause the issue, but you are supposed to get some exception asbout this
I don't know know what is undertow
, but you may check the SSL
configs from the doc.
You also need to check if both the server and client supports common cipher(s) and protocol(s)
For instance default package of JRE does not support AES_256
.
Upvotes: 0