Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jetty with SSL in Spring Boot 1.2.1

How should I configure Jetty with SSL connector in Spring Boot 1.2.x ?

The following configuration is working for Spring boot 1.1.6 but gives 'SslSocketConnector cannot be resolved to a type' error for the version 1.2.1.

@Configuration
@EnableAutoConfiguration
public class OptosoftOAuthSecurityApplication implements
        EmbeddedServletContainerCustomizer {

    public static void main(String[] args) {
        SpringApplication.run(OptosoftOAuthSecurityApplication.class, args);
    }

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

    public void customizeJetty(
            JettyEmbeddedServletContainerFactory containerFactory) {
        containerFactory.addServerCustomizers(jettyServerCustomizer());
    }

    @Bean
    public JettyServerCustomizer jettyServerCustomizer() {
        return 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);
                }

                // THIS CLASS cannot be resolved !!!!!!  
                SslSocketConnector sslConnector = new SslSocketConnector(
                        sslContextFactory);
                sslConnector.setPort(9443);
                sslConnector.setMaxIdleTime(60000);
                server.addConnector(sslConnector);
            }
        };
    }

    @Bean
    @ConditionalOnMissingBean(RequestContextListener.class)
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }
}

My pom.xml (Spring Boot version is 1.2.1 in parent POM):-

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <exclusions>
                <exclusion>
                    <artifactId>spring-boot-starter-tomcat</artifactId>
                    <groupId>org.springframework.boot</groupId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>
    </dependencies>
like image 278
Kumar Sambhav Avatar asked Feb 04 '15 11:02

Kumar Sambhav


1 Answers

The class you're trying to use is specific to Jetty 8 but Spring Boot 1.2.x uses Jetty 9 by default. In Spring Boot 1.2 you can now configure SSL declaratively in application.properties. This is illustrated in spring-boot-sample-jetty-ssl.

You can replace your EmbeddedServletContainerCustomizer implementation with the following properties declared in application.properties:

server.port = 9443
server.ssl.key-store = classpath:jetty-ssl.keystore
server.ssl.key-store-password = jetty6

Spring Boot only supports declarative configuration of a single connector. If you want the server to be accessible via HTTP and HTTPS then you'll have to configure one of them programatically. I'd recommend that the HTTP connector is configured programatically as there's less code involved:

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

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

        private void configureJetty(JettyEmbeddedServletContainerFactory jettyFactory) {
            jettyFactory.addServerCustomizers(new JettyServerCustomizer() {

                @Override
                public void customize(Server server) {
                    ServerConnector serverConnector = new ServerConnector(server);
                    serverConnector.setPort(8080);
                    server.addConnector(serverConnector);
                }
            });
        }
    };
}
like image 142
Andy Wilkinson Avatar answered Oct 06 '22 16:10

Andy Wilkinson