0

我有一个在 Tomcat 上运行的 Web 服务,并决定尝试使用 Undertow。总体来说还不错,但是我需要HTTPS支持,无法开启。这是一些helloworld代码:

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();

和 createSSLContext 方法:

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;
}

和 loadKeyStore 方法:

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;
    }
}

服务器正在启动,但尝试向https://localhost:8443/发送请求没有效果,没有日志或异常或一些反应。使用http://localhost:8443时会抛出异常

javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?

我对所有网络技术都是新手,所以这一切可能很奇怪。那么这里有什么问题呢?

4

2 回答 2

1

我有它的工作。如果您还没有这样做,请首先生成您的密钥:

#!/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

...然后在你的java代码中:

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);
    }
}

最后创建服务器

        Undertow webAppServer = Undertow.builder()
                .addHttpsListener(
                        port,
                        hostname,
                        serverSslContext(password1, password2, password3)
                )
                .setHandler(handlers, manager.start()))
                .build();
于 2016-09-07T11:11:35.560 回答
0

我不确定,但自签名和/或不受信任的证书会导致问题,但你应该得到一些例外

我不知道是什么undertow,但您可以检查SSL文档中的配置。

您还需要检查服务器和客户端是否都支持通用密码和协议,
例如 JRE 的默认包不支持AES_256

于 2015-08-22T22:13:43.887 回答