Поддерживает ли Spring Boot указание имени сервера (SNI)? - PullRequest
1 голос
/ 03 марта 2020

Поддерживает ли Spring Boot указание имени сервера (SNI)? В частности, возможно ли приложение Spring Boot (2.2.2.RELEASE), работающее со встроенным сервером Tomcat и упакованное как исполняемый файл JAR для поддержки нескольких сертификатов / доменов SSL на основе имени хоста входящего запроса?

Похоже, Tomcat поддерживает SNI (начиная с Tomcat 8.5), но я не уверен, как реализовать SNI в моем приложении Spring Boot.

Ответы [ 2 ]

1 голос
/ 06 марта 2020

Мне удалось проверить, что Spring Boot, работающий на встроенном сервере Tomcat, поддерживает указание имени сервера (SNI), используя следующую конфигурацию:

application.properties

abc.com.key-store=${user.dir}/abc.com.p12
xyz.com.key-store=${user.dir}/xyz.com.p12

ApplicationConfig. java

import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLHostConfigCertificate.Type;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;

@Configuration
public class ApplicationConfig {

    @Autowired
    private Environment env;

    @Bean
    public ServletWebServerFactory servletContainer() throws Exception {

        TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory() {
            // Override TomcatServletWebServerFactory methods (if needed)
        };

        // add SSL Connector
        tomcat.addAdditionalTomcatConnectors(createSSLConnectorForMultipleHosts());

        return tomcat;
    }


    private Connector createSSLConnectorForMultipleHosts() {
        Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");

        /**
         * Tomcat 9.0.x server SSL Connector for multiple hosts
         * 
        <Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol"
                   maxThreads="150" SSLEnabled="true"
                   defaultSSLHostConfigName="*.abc.com">
            <SSLHostConfig hostName="*.abc.com">
                <Certificate certificateKeystoreFile="conf/abc.com.p12"
                             type="RSA" />
            </SSLHostConfig>
            <SSLHostConfig hostName="*.xyz.com">
                <Certificate certificateKeystoreFile="conf/xyz.com.p12"
                             type="RSA" />
            </SSLHostConfig>
        </Connector>
         */

        try {
            connector.setScheme("https");
            connector.setSecure(true);
            connector.setPort(8443);
            connector.setAttribute("SSLEnabled", "true");
            connector.setAttribute("defaultSSLHostConfigName", "*.abc.com");

            // *.abc.com
            SSLHostConfig sslHostConfig = new SSLHostConfig();
            sslHostConfig.setHostName("*.abc.com");

            SSLHostConfigCertificate sslHostConfigCertificate = new SSLHostConfigCertificate(sslHostConfig, Type.RSA);
            sslHostConfigCertificate.setCertificateKeystoreFile(env.getProperty("abc.com.key-store"));

            sslHostConfig.addCertificate(sslHostConfigCertificate);
            connector.addSslHostConfig(sslHostConfig);

            // *.xyz.com
            sslHostConfig = new SSLHostConfig();
            sslHostConfig.setHostName("*.xyz.com");

            sslHostConfigCertificate = new SSLHostConfigCertificate(sslHostConfig, Type.RSA);
            sslHostConfigCertificate.setCertificateKeystoreFile(env.getProperty("xyz.com.key-store"));

            sslHostConfig.addCertificate(sslHostConfigCertificate);
            connector.addSslHostConfig(sslHostConfig);

            return connector;
        }
        catch (Exception ex) {
            throw new IllegalStateException("Exception creating SSL Connector: ", ex);
        }
    }

}
0 голосов
/ 03 марта 2020

Spring поддерживает конфигурацию разъема Tomcat. Я не запускал этот код, но это даст вам некоторое представление. Вы можете попробовать что-то вроде этого:

@Bean
public ServletWebServerFactory servletContainer() throws Exception {
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    tomcat.addAdditionalTomcatConnectors(createConnector());
    return tomcat;
}

public Connector createConnector() {
    Connector connector = new Connector("org.apache.coyote.http11.Http11AprProtocol");
    connector.setScheme("https");
    connector.setSecure(true);
    connector.setPort(8443);
    connector.addSslHostConfig(getSSLHostConfig());
    return connector;
}

private SSLHostConfig getSSLHostConfig() {
    SSLHostConfig sslHostConfig = new SSLHostConfig();
    sslHostConfig.setHostName("abc.com");
    sslHostConfig.setCertificateFile("abc.crt");
    sslHostConfig.setCaCertificateFile("xyz.crt");
    return sslHostConfig;
}
...