在 Undertow 中启用 HTTPS
Enabling HTTPS in Undertow
我们有一个可用的 Apache mod_ssl 配置。我想为 Undertow 启用 HTTPS 支持,以便它同时监听 http 和 https,从而避免对 Apache 的需求。
我查看了 Undertow 的 javadoc。 Undertow.Builder class 有两个具有以下签名的 addHttpsListener 方法:
public Builder addHttpsListener(int port, String host,
KeyManager[] keyManagers, TrustManager[] trustManagers);
public Builder addHttpsListener(int port, String host,
SSLContext sslContext) {
所以我似乎可以在使用 Builder API 引导 Undertow 时使用这些,例如
Undertow server = Undertow.builder()
.addHttpsListener(8443, "localhost", sslContext)
.build();
我不确定如何创建 SSLContext 变量,或者如何配置 KeyManagers 和 TrustManagers。
有了 mod_ssl 使用的证书文件,我该如何继续为 Undertow 启用 HTTPS?
更新:
根据 hwellmann 的回答,我重复使用了 SslContextFactory.createSslContext()
方法。在此之前,我必须将 public/private 密钥对转换为 PKCS12 格式并将其导入 Java 密钥库。
下面提供 SSL 转换 conversion/import 命令(取自 here and here),希望这些对任何人都有用:
# Convert to PKCS12
$ openssl pkcs12 -export -out output_cert.pfx -inkey input_cert.key -in input_cert.crt -certfile intermediate.crt
# Import into Java keystore
$ keytool -v -importkeystore -srckeystore output_cert.pfx -srcstoretype PKCS12 -destkeystore output_store.jks -deststoretype JKS
这并不是 Undertow 特有的,它只是一个从带有证书的密钥库构建 SSL 上下文的问题。
有关与 Undertow 一起使用的示例,请参阅 SslContextFactory.java
。
Undertow 源代码中有一个关于如何创建 SslContext 的示例:
https://github.com/undertow-io/undertow/blob/e8473ec35c420b782e072723d1e6338548def842/examples/src/main/java/io/undertow/examples/http2/Http2Server.java#L76
SSLContext sslContext = createSSLContext(loadKeyStore("server.keystore"), loadKeyStore("server.truststore"));
...
private static SSLContext createSSLContext(final KeyStore keyStore, final KeyStore trustStore) throws Exception {
KeyManager[] keyManagers;
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password("key"));
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;
}
...
private static KeyStore loadKeyStore(String storeLoc, String storePw) throws Exception {
InputStream stream = Files.newInputStream(Paths.get(storeLoc));
if(stream == null) {
throw new IllegalArgumentException("Could not load keystore");
}
try(InputStream is = stream) {
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(is, storePw.toCharArray());
return loadedKeystore;
}
}
我们有一个可用的 Apache mod_ssl 配置。我想为 Undertow 启用 HTTPS 支持,以便它同时监听 http 和 https,从而避免对 Apache 的需求。
我查看了 Undertow 的 javadoc。 Undertow.Builder class 有两个具有以下签名的 addHttpsListener 方法:
public Builder addHttpsListener(int port, String host,
KeyManager[] keyManagers, TrustManager[] trustManagers);
public Builder addHttpsListener(int port, String host,
SSLContext sslContext) {
所以我似乎可以在使用 Builder API 引导 Undertow 时使用这些,例如
Undertow server = Undertow.builder()
.addHttpsListener(8443, "localhost", sslContext)
.build();
我不确定如何创建 SSLContext 变量,或者如何配置 KeyManagers 和 TrustManagers。 有了 mod_ssl 使用的证书文件,我该如何继续为 Undertow 启用 HTTPS?
更新:
根据 hwellmann 的回答,我重复使用了 SslContextFactory.createSslContext()
方法。在此之前,我必须将 public/private 密钥对转换为 PKCS12 格式并将其导入 Java 密钥库。
下面提供 SSL 转换 conversion/import 命令(取自 here and here),希望这些对任何人都有用:
# Convert to PKCS12
$ openssl pkcs12 -export -out output_cert.pfx -inkey input_cert.key -in input_cert.crt -certfile intermediate.crt
# Import into Java keystore
$ keytool -v -importkeystore -srckeystore output_cert.pfx -srcstoretype PKCS12 -destkeystore output_store.jks -deststoretype JKS
这并不是 Undertow 特有的,它只是一个从带有证书的密钥库构建 SSL 上下文的问题。
有关与 Undertow 一起使用的示例,请参阅 SslContextFactory.java
。
Undertow 源代码中有一个关于如何创建 SslContext 的示例: https://github.com/undertow-io/undertow/blob/e8473ec35c420b782e072723d1e6338548def842/examples/src/main/java/io/undertow/examples/http2/Http2Server.java#L76
SSLContext sslContext = createSSLContext(loadKeyStore("server.keystore"), loadKeyStore("server.truststore"));
...
private static SSLContext createSSLContext(final KeyStore keyStore, final KeyStore trustStore) throws Exception {
KeyManager[] keyManagers;
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, password("key"));
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;
}
...
private static KeyStore loadKeyStore(String storeLoc, String storePw) throws Exception {
InputStream stream = Files.newInputStream(Paths.get(storeLoc));
if(stream == null) {
throw new IllegalArgumentException("Could not load keystore");
}
try(InputStream is = stream) {
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(is, storePw.toCharArray());
return loadedKeystore;
}
}