Spring Boot + Jetty + SSL端口

时间:2014-06-09 14:12:06

标签: embedded-jetty spring-boot

如何配置Spring Boot以在443处使用HTTPS端口运行Jetty。配置还应注意生成密钥。

简而言之,以下maven插件的等效配置: -

<plugin>
  <groupId>org.codehaus.mojo</groupId>
  <artifactId>keytool-maven-plugin</artifactId>
  <version>1.3</version>
  <executions>
    <execution>
      <phase>generate-resources</phase>
      <id>clean</id>
      <goals>
        <goal>clean</goal>
      </goals>
    </execution>
    <execution>
      <phase>generate-resources</phase>
      <id>genkey</id>
      <goals>
        <goal>generateKeyPair</goal>
      </goals>
    </execution>
  </executions>
  <configuration>
    <keystore>${project.build.directory}/jetty-ssl.keystore</keystore>
    <dname>cn=my.hostname.tld</dname>
    <!-- put your CN here -->
    <keypass>jetty6</keypass>
    <storepass>jetty6</storepass>
    <alias>jetty6</alias>
    <keyalg>RSA</keyalg>
  </configuration>
</plugin>

和: -

<plugin>
  <groupId>org.mortbay.jetty</groupId>
  <artifactId>maven-jetty-plugin</artifactId>
  <version>6.1.26</version>
  <configuration>
    <jvmArgs>-Xmx2048m -Xms1536m -XX:PermSize=128m -XX:MaxPermSize=256m</jvmArgs>
    <!-- http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin -->
    <scanIntervalSeconds>10</scanIntervalSeconds>
    <connectors>
      <connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">
        <port>9999</port>
        <maxIdleTime>60000</maxIdleTime>
      </connector>
      <connector implementation="org.mortbay.jetty.security.SslSocketConnector">
        <port>9993</port>
        <maxIdleTime>60000</maxIdleTime>
        <keystore>${project.build.directory}/jetty-ssl.keystore</keystore>
        <password>jetty6</password>
        <keyPassword>jetty6</keyPassword>
      </connector>
    </connectors>
    <contextPath>/</contextPath>
  </configuration>
</plugin>

4 个答案:

答案 0 :(得分:8)

从Spring Boot 1.1.7开始,您可以将Jetty和Tomcat配置为通过属性文件中的三个属性使用SSL,如Spring Boot documentation

所示

通过这些属性配置SSL将启用HTTPS并禁用HTTP,因为仅使用属性文件不允许这两者。如果要同时同时提供Spring recommends,请通过属性配置HTTPS(SSL)并以编程方式配置HTTP。

答案 1 :(得分:6)

我找到了这个解决方案。这对我来说可以。 此方法可以同时支持HTTP和HTTPS。

@Component
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {

        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            if (container instanceof JettyEmbeddedServletContainerFactory) {
                customizeJetty((JettyEmbeddedServletContainerFactory) container);
            }
        }

        private void customizeJetty(JettyEmbeddedServletContainerFactory container) {

    container.addServerCustomizers(new JettyServerCustomizer() {

        @Override
        public void customize(Server server) {

            // HTTP
            ServerConnector connector = new ServerConnector(server);
            connector.setPort(requestHttpPort());

            // HTTPS
            SslContextFactory sslContextFactory = new SslContextFactory();
            sslContextFactory.setKeyStorePath("mykeystore.jks");
            sslContextFactory.setKeyStorePassword("1234");

            HttpConfiguration https = new HttpConfiguration();
            https.addCustomizer(new SecureRequestCustomizer());

            ServerConnector sslConnector = new ServerConnector(
                    server,
                    new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
                    new HttpConnectionFactory(https));
            sslConnector.setPort(requestHttpsPort());

            server.setConnectors(new Connector[] { connector, sslConnector });

        }
    });
}

答案 2 :(得分:3)

要将SSL连接器添加到Jetty,您需要在应用程序的配置中声明EmbeddedServletContainerCustomizer bean。这最终将使您能够访问Jetty Server实例,您可以使用Jetty的API进行所需的配置更改。类似的东西:

@Bean
public EmbeddedServletContainerCustomizer servletContainerCustomizer() {
    return new EmbeddedServletContainerCustomizer() {

        @Override
        public void customize(ConfigurableEmbeddedServletContainer container) {
            if (container instanceof JettyEmbeddedServletContainerFactory) {
                customizeJetty((JettyEmbeddedServletContainerFactory) container);
            }
        }

        private void customizeJetty(JettyEmbeddedServletContainerFactory factory) {
            factory.addServerCustomizers(new JettyServerCustomizer() {

                @Override
                public void customize(Server server) {
                    SslContextFactory sslContextFactory = new SslContextFactory();
                    sslContextFactory.setKeyStorePassword("jetty6");
                    try {
                        sslContextFactory.setKeyStorePath(ResourceUtils.getFile(
                                "classpath:jetty-ssl.keystore").getAbsolutePath());
                    }
                    catch (FileNotFoundException ex) {
                        throw new IllegalStateException("Could not load keystore", ex);
                    }
                    SslSocketConnector sslConnector = new SslSocketConnector(
                            sslContextFactory);
                    sslConnector.setPort(9993);
                    sslConnector.setMaxIdleTime(60000);
                    server.addConnector(sslConnector);
                }
            });
        }
    };
}

Spring Boot中没有支持自动生成密钥库。我继续使用keytool Maven插件。

答案 3 :(得分:0)

对于Spring Boot较新版本(2.1.x)。尝试以下代码,基本上已将EmbeddedServletContainerCustomizer和ConfigurableEmbeddedServletContainer替换如下:

import org.eclipse.jetty.http.HttpVersion;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.HttpConnectionFactory;
import org.eclipse.jetty.server.SecureRequestCustomizer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.server.SslConnectionFactory;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.ResourceUtils;

@Configuration
public class BeanConfiguration {

    @Bean
    public WebServerFactoryCustomizer<JettyServletWebServerFactory> webServerFactoryCustomizer() {

        return new WebServerFactoryCustomizer<JettyServletWebServerFactory>() {

            @Override
            public void customize(JettyServletWebServerFactory factory) {

                factory.addServerCustomizers(new JettyServerCustomizer() {

                    @Override
                    public void customize(Server server) {

                        ServerConnector httpConnector = new ServerConnector(server);
                        httpConnector.setPort(8080);

                        SslContextFactory sslContextFactory = new SslContextFactory();
                        try {
                            sslContextFactory
                                    .setKeyStorePath(ResourceUtils.getFile("classpath:keystore.jks").getAbsolutePath());
                        } catch (Exception e) {
                        }

                        sslContextFactory.setKeyStorePassword("password");

                        HttpConfiguration httpsConfiguration = new HttpConfiguration();
                        httpsConfiguration.addCustomizer(new SecureRequestCustomizer());

                        ServerConnector httpsConnector = new ServerConnector(server,
                                new SslConnectionFactory(sslContextFactory, HttpVersion.HTTP_1_1.asString()),
                                new HttpConnectionFactory(httpsConfiguration));
                        httpsConnector.setPort(8090);

                        server.setConnectors(new Connector[] {httpConnector, httpsConnector});
                    }
                });

            }
        };
    }
}