Как настроить Spring Загрузка для запуска портов HTTPS/HTTP

Spring boot имеет некоторые свойства для настройки веб-порта и настроек 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. Буду признателен за любую помощь!

Ответ 1

Настройка Spring Boot с использованием свойств, позволяет настроить только один разъем. Что вам нужно, это несколько разъемов, и для этого вам нужно написать класс конфигурации. Следуйте инструкциям в

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

Вы можете найти рабочий пример настройки https через свойства, а затем http через EmbeddedServletContainerCustomizer ниже

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

Ответ 2

В настоящее время принятый ответ работает отлично, но требует некоторой адаптации, если вы хотите, чтобы он работал с Spring Boot 2.0.0 и далее:

@Component
public class HttpServer {
  @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;
  }
}

или версия kotlin:

@Component
class HttpServer {
  @Bean
  fun servletContainer(@Value("\${server.http.port}") httpPort: Int): ServletWebServerFactory {
    val connector = Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL)
    connector.setPort(httpPort)

    val tomcat = TomcatServletWebServerFactory()
    tomcat.addAdditionalTomcatConnectors(connector)
    return tomcat
  }
}

Ответ 3

Ниже приведен простой пример того, как включить оба порта 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<UndertowServletWebServerFactory> containerCustomizer() {
    return (WebServerFactoryCustomizer) factory -> {
        UndertowServletWebServerFactory undertowFactory = (UndertowServletWebServerFactory) factory;
        undertowFactory.getBuilderCustomizers().add(builder -> {
            builder.addHttpListener(httpPort, httpInterface);
        });
    };
}

}

HTTPS по конфигурации

Spring может открыть один из свойств чтения порта HTTP или HTTPS из доступного источника ресурсов. Если вы добавите соответствующую конфигурацию, как показано ниже, это будет достаточно хорошо, чтобы открыть HTTP-порт.

#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 с помощью ручной настройки

Вы можете открыть другой порт SSL так же, как вы открыли порт HTTP, если хотите, сделав это

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

Ответ 4

Другое решение Spring 2.x 2.x:

private static final int HTTP_PORT = 80;
private static final int HTTPS_PORT = 443;
private static final String HTTP = "http";
private static final String USER_CONSTRAINT = "CONFIDENTIAL";

@Bean
public ServletWebServerFactory servletContainer() {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
        @Override
        protected void postProcessContext(Context context) {
            SecurityConstraint securityConstraint = new SecurityConstraint();
            securityConstraint.setUserConstraint(USER_CONSTRAINT);
            SecurityCollection collection = new SecurityCollection();
            collection.addPattern("/*");
            securityConstraint.addCollection(collection);
            context.addConstraint(securityConstraint);
        }
    };
    tomcat.addAdditionalTomcatConnectors(redirectConnector());
    return tomcat;
}

private Connector redirectConnector() {
    Connector connector = new Connector(
            TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
    connector.setScheme(HTTP);
    connector.setPort(HTTP_PORT);
    connector.setSecure(false);
    connector.setRedirectPort(HTTPS_PORT);
    return connector;
}

И установите в свойствах server.port = 443

Ответ 5

Взгляните на: https://github.com/creactiviti/spring-boot-starter-acme. Это позволяет легко генерировать сертификат SSL на основе LetsEncrypt.

Из README:

  1. Добавьте модуль в файл pom.xml в качестве зависимости.

  2. Создайте свой проект.

  3. Разверните его на целевой компьютер и укажите свое доменное имя на IP-адрес этой машины. LetsEncrypt подтверждает ваше право собственности на домен, выполнив обратный вызов к конечной точке http://your-domain/.well-known/acme-challenge/ {token}, выставленной этим модулем.

  4. Убедитесь, что ваш сервер имеет openssl, доступный в его $ PATH.

  5. Чтобы активировать spring-boot-starter-acme и сгенерировать сертификат, выполните:

    sudo java -Dserver.port=80 -Dacme.enabled=true -Dacme.domain-name=<YOUR_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

Ответ 7

Лучшие ответы все великолепны и, вероятно, работают, но я использовал Undertow с JHipster, поэтому они не спомогли мне (и это был основной результат поиска). Правильный код для Undertow упоминается в этой проблеме, а именно:

@Bean
public UndertowServletWebServerFactory embeddedServletContainerFactory() {
    UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
    factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
        @Override
        public void customize(Undertow.Builder builder) {
            builder.addHttpListener(8080, "0.0.0.0");
        }
    });
    return factory;
}