如何设置Spring Boot来运行HTTPS / HTTP端口

Spring引导具有一些属性来配置Web端口和SSL设置,但是一旦设置了SSL证书,http端口就会变成https端口。

那么,我怎样才能让两个端口都在其上运行,例如:80和443同时运行?

如您所见,只有一个端口的属性,在这种情况下启用了“server.ssl”,这使得http端口自动被禁用。

############## ### Server ### ############## server.port=9043 server.session-timeout=1800 server.ssl.key-store=file:///C:/Temp/config/localhost.jks server.ssl.key-store-password=localhost server.ssl.key-password=localhost server.ssl.trust-store=file:///C:/Temp/config/localhost.jks server.ssl.trust-store-password=localhost 

我试图使用甚至Tomcat或Undertow。 我很感激任何帮助!

使用属性的Spring Boot配置允许仅配置一个连接器。 你需要的是多个连接器,为此你必须编写一个Configuration类。 按照说明操作

https://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html

您可以在下面找到通过属性配置https的工作示例,然后通过http来嵌入ServSerletContainerCustomizer

http://izeye.blogspot.com/2015/01/configure-http-and-https-in-spring-boot.html?showComment=1461632100718#c4988529876932015554

 server: port: 8080 ssl: enabled: true keyStoreType: PKCS12 key-store: /path/to/keystore.p12 key-store-password: password http: port: 8079 

 @Configuration public class TomcatConfig { @Value("${server.http.port}") private int httpPort; @Bean public EmbeddedServletContainerCustomizer containerCustomizer() { return new EmbeddedServletContainerCustomizer() { @Override public void customize(ConfigurableEmbeddedServletContainer container) { if (container instanceof TomcatEmbeddedServletContainerFactory) { TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) container; Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL); connector.setPort(httpPort); containerFactory.addAdditionalTomcatConnectors(connector); } } }; } } 

当前接受的答案非常有效,但如果您希望它与Spring Boot 2.0.0及以后版本一起使用,则需要进行一些调整:

 @Bean public ServletWebServerFactory servletContainer(@Value("${server.http.port}") int httpPort) { Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL); connector.setPort(httpPort); TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory(); tomcat.addAdditionalTomcatConnectors(connector); return tomcat; } 

看看: https : //github.com/creactiviti/spring-boot-starter-acme 。 它使得自动生成基于LetsEncrypt的SSL证书变得非常容易。

来自README:

  1. 将模块作为依赖项添加到pom.xml文件中。

  2. 建立你的项目。

  3. 将其部署到目标计算机并将您的域名指向该计算机的IP地址。 LetsEncrypt通过回调此模块公开的http://your-domain/.well-known/acme-challenge/ {token}端点来validation您对域的所有权。

  4. 确保您的服务器在$ PATH上有openssl可用。

  5. 要激活spring-boot-starter-acme并生成证书,请执行:

    sudo java -Dserver.port=80 -Dacme.enabled=true -Dacme.domain-name= -Dacme.accept-terms-of-service=true -jar mysecureapp-0.0.1-SNAPSHOT.jar

  6. 检查控制台是否已成功生成证书。

  7. 停止您的应用程序并将其配置为使用生成的证书:

    server.port=443 server.ssl.key-store=keystore.p12 server.ssl.key-store-password=password server.ssl.keyStoreType=PKCS12

Bellow是一个简单的例子,说明如何启用两个HTTP / HTTPS端口。

Spring Boot只允许通过配置打开一个端口。 必须以编程方式打开第二个端口。

首先以编程方式打开HTTP端口。

 import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory; import org.springframework.boot.web.server.WebServerFactoryCustomizer; @Configuration public class UndertowConfig { @Value("${server.http.port}") private int httpPort; @Value("${server.http.interface}") private String httpInterface; @Bean public WebServerFactoryCustomizer containerCustomizer() { return (WebServerFactoryCustomizer) factory -> { UndertowServletWebServerFactory undertowFactory = (UndertowServletWebServerFactory) factory; undertowFactory.getBuilderCustomizers().add(builder -> { builder.addHttpListener(httpPort, httpInterface); }); }; } 

}

HTTPS配置

Spring可以从可用属性源打开HTTP或HTTPS端口读取属性。 如果您添加适当的配置,如下所示,将HTTPs端口打开就足够了。

 #default secured port (Spring will open it automatically) server.port=8443 #additional HTTP port (will open it in UndertowConfig) server.http.port=8080 #Open to the world server.http.interface=0.0.0.0 #These settings tell Spring to open SSL port server.ssl.keystore=file:${APP_BASE}/conf/server/ssl_selfsigned/server.keystore server.ssl.key-store-password=xyz server.ssl.key-password=xyz 

通过手动设置HTTPS

如果您愿意,可以像打开HTTP端口一样打开另一个SSL端口

  .addHttpsListener(ssl_port, httpInterface, getSSLContext()); 

这是您创建SSL上下文的方法

 import javax.net.ssl.*; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyStore; public SSLContext getSSLContext() throws Exception { return createSSLContext(loadKeyStore(serverKeystore,keyStorePassword), loadKeyStore(serverTruststore,trustStorePassword)); } private SSLContext createSSLContext(final KeyStore keyStore, final KeyStore trustStore) throws Exception { KeyManager[] keyManagers; KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); keyManagerFactory.init(keyStore, keyStorePassword.toCharArray()); 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(final String storeLoc, final 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; } }