Upgrade to Tomcat 8.5.3
This commit changes the default version of Tomcat to 8.5.3 while also retaining support for Tomcat 8.0 and 7.0. The main difference in 8.5 is that the ServerSocketFactory abstraction that allowed the TrustStore and KeyStore to be configured programatically no longer exists. This logic has been replaced with the use of a custom URL protocol (springbootssl) that provides access to the key store and trust store of an SslStoreProvider. In addition to working with 8.5, this approach has the advantage of also working with 8.0 and 7.0. Closes gh-6164
This commit is contained in:
parent
06b81cf16f
commit
f28e3d54c5
|
@ -308,8 +308,8 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -173,7 +173,7 @@
|
|||
<thymeleaf-layout-dialect.version>1.4.0</thymeleaf-layout-dialect.version>
|
||||
<thymeleaf-extras-data-attribute.version>1.3</thymeleaf-extras-data-attribute.version>
|
||||
<thymeleaf-extras-java8time.version>2.1.0.RELEASE</thymeleaf-extras-java8time.version>
|
||||
<tomcat.version>8.0.33</tomcat.version>
|
||||
<tomcat.version>8.5.3</tomcat.version>
|
||||
<undertow.version>1.3.22.Final</undertow.version>
|
||||
<velocity.version>1.7</velocity.version>
|
||||
<velocity-tools.version>2.0</velocity-tools.version>
|
||||
|
@ -1314,11 +1314,6 @@
|
|||
<artifactId>tomcat-embed-jasper</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-websocket</artifactId>
|
||||
|
@ -1334,6 +1329,11 @@
|
|||
<artifactId>tomcat-jsp-api</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
<version>${tomcat.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.velocity</groupId>
|
||||
<artifactId>velocity</artifactId>
|
||||
|
|
|
@ -118,8 +118,8 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -300,8 +300,8 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -193,7 +193,7 @@ The following sample applications are provided:
|
|||
| Embedded Tomcat
|
||||
|
||||
| link:spring-boot-sample-tomcat-jsp[spring-boot-sample-tomcat-jsp]
|
||||
| Web application that uses JSP templates with Tomcat 8
|
||||
| Web application that uses JSP templates with Tomcat
|
||||
|
||||
| link:spring-boot-sample-tomcat-multi-connectors[spring-boot-sample-tomcat-multi-connectors]
|
||||
| Web application that uses Tomcat configured with multiple connectors
|
||||
|
@ -204,6 +204,12 @@ The following sample applications are provided:
|
|||
| link:spring-boot-sample-tomcat7-jsp[spring-boot-sample-tomcat7-jsp]
|
||||
| Web application that uses JSP templates with Tomcat 7
|
||||
|
||||
| link:spring-boot-sample-tomcat7-ssl[spring-boot-sample-tomcat7-ssl]
|
||||
| Web application that uses Tomcat 7 configured with SSL
|
||||
|
||||
| link:spring-boot-sample-tomcat80-ssl[spring-boot-sample-tomcat80-ssl]
|
||||
| Web application that uses Tomcat 8.0 configured with SSL
|
||||
|
||||
| link:spring-boot-sample-traditional[spring-boot-sample-traditional]
|
||||
| Traditional WAR packaging (but also executable using `java -jar`)
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@
|
|||
<module>spring-boot-sample-tomcat-ssl</module>
|
||||
<module>spring-boot-sample-tomcat-multi-connectors</module>
|
||||
<module>spring-boot-sample-tomcat7-jsp</module>
|
||||
<module>spring-boot-sample-tomcat7-ssl</module>
|
||||
<module>spring-boot-sample-tomcat80-ssl</module>
|
||||
<module>spring-boot-sample-traditional</module>
|
||||
<module>spring-boot-sample-undertow</module>
|
||||
<module>spring-boot-sample-undertow-ssl</module>
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<m2eclipse.wtp.contextRoot>/</m2eclipse.wtp.contextRoot>
|
||||
<tomcat.version>7.0.69</tomcat.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-tomcat-ssl</artifactId>
|
||||
<name>Spring Boot Tomcat Sample</name>
|
||||
<name>Spring Boot Tomcat SSL Sample</name>
|
||||
<description>Spring Boot Tomcat SSL Sample</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
|
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-tomcat7-ssl</artifactId>
|
||||
<name>Spring Boot Tomcat 7 SSL Sample</name>
|
||||
<description>Spring Boot Tomcat 7 SSL Sample</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<tomcat.version>7.0.69</tomcat.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.tomcat.ssl;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleTomcatSslApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(SampleTomcatSslApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.tomcat.ssl.web;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
public class SampleController {
|
||||
|
||||
@GetMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld() {
|
||||
return "Hello, world";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
server.port = 8443
|
||||
server.ssl.key-store = classpath:sample.jks
|
||||
server.ssl.key-store-password = secret
|
||||
server.ssl.key-password = password
|
Binary file not shown.
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.tomcat.ssl;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate.HttpClientOption;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@DirtiesContext
|
||||
public class SampleTomcatSslApplicationTests {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void testHome() throws Exception {
|
||||
TestRestTemplate testRestTemplate = new TestRestTemplate(HttpClientOption.SSL);
|
||||
ResponseEntity<String> entity = testRestTemplate
|
||||
.getForEntity("https://localhost:" + this.port, String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).isEqualTo("Hello, world");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<!-- Your own application should inherit from spring-boot-starter-parent -->
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-samples</artifactId>
|
||||
<version>1.4.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-tomcat-ssl</artifactId>
|
||||
<name>Spring Boot Tomcat 8.0 SSL Sample</name>
|
||||
<description>Spring Boot Tomcat 8.0 SSL Sample</description>
|
||||
<url>http://projects.spring.io/spring-boot/</url>
|
||||
<organization>
|
||||
<name>Pivotal Software, Inc.</name>
|
||||
<url>http://www.spring.io</url>
|
||||
</organization>
|
||||
<properties>
|
||||
<main.basedir>${basedir}/../..</main.basedir>
|
||||
<tomcat.version>8.0.33</tomcat.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-tomcat</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.httpcomponents</groupId>
|
||||
<artifactId>httpclient</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.tomcat.ssl;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class SampleTomcatSslApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(SampleTomcatSslApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.tomcat.ssl.web;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
public class SampleController {
|
||||
|
||||
@GetMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld() {
|
||||
return "Hello, world";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,4 @@
|
|||
server.port = 8443
|
||||
server.ssl.key-store = classpath:sample.jks
|
||||
server.ssl.key-store-password = secret
|
||||
server.ssl.key-password = password
|
Binary file not shown.
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package sample.tomcat.ssl;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.boot.context.embedded.LocalServerPort;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||
import org.springframework.boot.test.web.client.TestRestTemplate.HttpClientOption;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
|
||||
@DirtiesContext
|
||||
public class SampleTomcatSslApplicationTests {
|
||||
|
||||
@LocalServerPort
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void testHome() throws Exception {
|
||||
TestRestTemplate testRestTemplate = new TestRestTemplate(HttpClientOption.SSL);
|
||||
ResponseEntity<String> entity = testRestTemplate
|
||||
.getForEntity("https://localhost:" + this.port, String.class);
|
||||
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
|
||||
assertThat(entity.getBody()).isEqualTo("Hello, world");
|
||||
}
|
||||
|
||||
}
|
|
@ -28,8 +28,8 @@
|
|||
<artifactId>tomcat-embed-el</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
|
|
|
@ -112,8 +112,8 @@
|
|||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -110,8 +110,8 @@
|
|||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.tomcat.embed</groupId>
|
||||
<artifactId>tomcat-embed-logging-juli</artifactId>
|
||||
<groupId>org.apache.tomcat</groupId>
|
||||
<artifactId>tomcat-juli</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -1,98 +0,0 @@
|
|||
/*
|
||||
* Copyright 2012-2016 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.boot.context.embedded.tomcat;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.security.KeyStore;
|
||||
|
||||
import org.apache.tomcat.util.net.AbstractEndpoint;
|
||||
import org.apache.tomcat.util.net.SSLUtil;
|
||||
import org.apache.tomcat.util.net.ServerSocketFactory;
|
||||
import org.apache.tomcat.util.net.jsse.JSSEImplementation;
|
||||
import org.apache.tomcat.util.net.jsse.JSSESocketFactory;
|
||||
|
||||
import org.springframework.boot.context.embedded.SslStoreProvider;
|
||||
|
||||
/**
|
||||
* {@link JSSEImplementation} for embedded Tomcat that supports {@link SslStoreProvider}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Venil Noronha
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public class TomcatEmbeddedJSSEImplementation extends JSSEImplementation {
|
||||
|
||||
@Override
|
||||
public ServerSocketFactory getServerSocketFactory(AbstractEndpoint<?> endpoint) {
|
||||
return new SocketFactory(endpoint);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SSLUtil getSSLUtil(AbstractEndpoint<?> endpoint) {
|
||||
return new SocketFactory(endpoint);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link JSSESocketFactory} that supports {@link SslStoreProvider}.
|
||||
*/
|
||||
static class SocketFactory extends JSSESocketFactory {
|
||||
|
||||
private final SslStoreProvider sslStoreProvider;
|
||||
|
||||
SocketFactory(AbstractEndpoint<?> endpoint) {
|
||||
super(endpoint);
|
||||
this.sslStoreProvider = (SslStoreProvider) endpoint
|
||||
.getAttribute("sslStoreProvider");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeyStore getKeystore(String type, String provider, String pass)
|
||||
throws IOException {
|
||||
if (this.sslStoreProvider != null) {
|
||||
try {
|
||||
KeyStore store = this.sslStoreProvider.getKeyStore();
|
||||
if (store != null) {
|
||||
return store;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
return super.getKeystore(type, provider, pass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected KeyStore getTrustStore(String keystoreType, String keystoreProvider)
|
||||
throws IOException {
|
||||
if (this.sslStoreProvider != null) {
|
||||
try {
|
||||
KeyStore store = this.sslStoreProvider.getTrustStore();
|
||||
if (store != null) {
|
||||
return store;
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
return super.getTrustStore(keystoreType, keystoreProvider);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -16,12 +16,19 @@
|
|||
|
||||
package org.springframework.boot.context.embedded.tomcat;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.net.URLStreamHandler;
|
||||
import java.net.URLStreamHandlerFactory;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.KeyStore;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
@ -48,11 +55,13 @@ import org.apache.catalina.session.ManagerBase;
|
|||
import org.apache.catalina.session.StandardManager;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.startup.Tomcat.FixContextListener;
|
||||
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.ProtocolHandler;
|
||||
import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
|
||||
import org.apache.coyote.http11.AbstractHttp11Protocol;
|
||||
import org.apache.coyote.http11.Http11NioProtocol;
|
||||
import org.apache.tomcat.util.net.SSLHostConfig;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
|
@ -301,7 +310,7 @@ public class TomcatEmbeddedServletContainerFactory
|
|||
Compression compression = getCompression();
|
||||
protocol.setCompression("on");
|
||||
protocol.setCompressionMinSize(compression.getMinResponseSize());
|
||||
protocol.setCompressableMimeTypes(
|
||||
protocol.setCompressableMimeType(
|
||||
StringUtils.arrayToCommaDelimitedString(compression.getMimeTypes()));
|
||||
if (getCompression().getExcludedUserAgents() != null) {
|
||||
protocol.setNoCompressionUserAgents(
|
||||
|
@ -323,13 +332,33 @@ public class TomcatEmbeddedServletContainerFactory
|
|||
protocol.setKeystorePass(ssl.getKeyStorePassword());
|
||||
protocol.setKeyPass(ssl.getKeyPassword());
|
||||
protocol.setKeyAlias(ssl.getKeyAlias());
|
||||
protocol.setCiphers(StringUtils.arrayToCommaDelimitedString(ssl.getCiphers()));
|
||||
String ciphers = StringUtils.arrayToCommaDelimitedString(ssl.getCiphers());
|
||||
protocol.setCiphers(StringUtils.hasText(ciphers) ? ciphers : null);
|
||||
if (ssl.getEnabledProtocols() != null) {
|
||||
protocol.setProperty("sslEnabledProtocols",
|
||||
StringUtils.arrayToCommaDelimitedString(ssl.getEnabledProtocols()));
|
||||
try {
|
||||
for (SSLHostConfig sslHostConfig : protocol.findSslHostConfigs()) {
|
||||
sslHostConfig.setProtocols(StringUtils
|
||||
.arrayToCommaDelimitedString(ssl.getEnabledProtocols()));
|
||||
}
|
||||
}
|
||||
catch (NoSuchMethodError ex) {
|
||||
// Tomcat 8.0.x or earlier
|
||||
Assert.isTrue(
|
||||
protocol.setProperty("sslEnabledProtocols",
|
||||
StringUtils.arrayToCommaDelimitedString(
|
||||
ssl.getEnabledProtocols())),
|
||||
"Failed to set sslEnabledProtocols");
|
||||
}
|
||||
}
|
||||
if (getSslStoreProvider() != null) {
|
||||
configureSslStoreProvider(protocol, getSslStoreProvider());
|
||||
TomcatURLStreamHandlerFactory instance = TomcatURLStreamHandlerFactory
|
||||
.getInstance();
|
||||
instance.addUserFactory(
|
||||
new SslStoreProviderUrlStreamHandlerFactory(getSslStoreProvider()));
|
||||
protocol.setKeystoreFile(
|
||||
SslStoreProviderUrlStreamHandlerFactory.KEY_STORE_URL);
|
||||
protocol.setTruststoreFile(
|
||||
SslStoreProviderUrlStreamHandlerFactory.TRUST_STORE_URL);
|
||||
}
|
||||
else {
|
||||
configureSslKeyStore(protocol, ssl);
|
||||
|
@ -350,10 +379,6 @@ public class TomcatEmbeddedServletContainerFactory
|
|||
SslStoreProvider sslStoreProvider) {
|
||||
Assert.isInstanceOf(Http11NioProtocol.class, protocol,
|
||||
"SslStoreProvider can only be used with Http11NioProtocol");
|
||||
((Http11NioProtocol) protocol).getEndpoint().setAttribute("sslStoreProvider",
|
||||
sslStoreProvider);
|
||||
protocol.setSslImplementationName(
|
||||
TomcatEmbeddedJSSEImplementation.class.getName());
|
||||
}
|
||||
|
||||
private void configureSslKeyStore(AbstractHttp11JsseProtocol<?> protocol, Ssl ssl) {
|
||||
|
@ -677,6 +702,89 @@ public class TomcatEmbeddedServletContainerFactory
|
|||
return this.uriEncoding;
|
||||
}
|
||||
|
||||
/**
|
||||
* A {@link URLStreamHandlerFactory} that provides a {@link URLStreamHandler} for
|
||||
* accessing an {@link SslStoreProvider}'s key store and trust store from a URL.
|
||||
*/
|
||||
private static final class SslStoreProviderUrlStreamHandlerFactory
|
||||
implements URLStreamHandlerFactory {
|
||||
|
||||
private static final String PROTOCOL = "springbootssl";
|
||||
|
||||
private static final String KEY_STORE_PATH = "keyStore";
|
||||
|
||||
private static final String KEY_STORE_URL = PROTOCOL + ":" + KEY_STORE_PATH;
|
||||
|
||||
private static final String TRUST_STORE_PATH = "trustStore";
|
||||
|
||||
private static final String TRUST_STORE_URL = PROTOCOL + ":" + TRUST_STORE_PATH;
|
||||
|
||||
private final SslStoreProvider sslStoreProvider;
|
||||
|
||||
private SslStoreProviderUrlStreamHandlerFactory(
|
||||
SslStoreProvider sslStoreProvider) {
|
||||
this.sslStoreProvider = sslStoreProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URLStreamHandler createURLStreamHandler(String protocol) {
|
||||
if (PROTOCOL.equals(protocol)) {
|
||||
return new URLStreamHandler() {
|
||||
|
||||
@Override
|
||||
protected URLConnection openConnection(URL url) throws IOException {
|
||||
try {
|
||||
if (KEY_STORE_PATH.equals(url.getPath())) {
|
||||
return new KeyStoreUrlConnection(url,
|
||||
SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider
|
||||
.getKeyStore());
|
||||
}
|
||||
if (TRUST_STORE_PATH.equals(url.getPath())) {
|
||||
return new KeyStoreUrlConnection(url,
|
||||
SslStoreProviderUrlStreamHandlerFactory.this.sslStoreProvider
|
||||
.getTrustStore());
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
throw new IOException("Invalid path: " + url.getPath());
|
||||
}
|
||||
};
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private static final class KeyStoreUrlConnection extends URLConnection {
|
||||
|
||||
private final KeyStore keyStore;
|
||||
|
||||
private KeyStoreUrlConnection(URL url, KeyStore keyStore) {
|
||||
super(url);
|
||||
this.keyStore = keyStore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getInputStream() throws IOException {
|
||||
|
||||
try {
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
this.keyStore.store(stream, new char[0]);
|
||||
return new ByteArrayInputStream(stream.toByteArray());
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private static class TomcatErrorPage {
|
||||
|
||||
private static final String ERROR_PAGE_CLASS = "org.apache.tomcat.util.descriptor.web.ErrorPage";
|
||||
|
@ -752,8 +860,7 @@ public class TomcatEmbeddedServletContainerFactory
|
|||
*/
|
||||
private static class StoreMergedWebXmlListener implements LifecycleListener {
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
private final String MERGED_WEB_XML = org.apache.tomcat.util.scan.Constants.MERGED_WEB_XML;
|
||||
private static final String MERGED_WEB_XML = "org.apache.tomcat.util.scan.MergedWebXml";
|
||||
|
||||
@Override
|
||||
public void lifecycleEvent(LifecycleEvent event) {
|
||||
|
@ -764,8 +871,10 @@ public class TomcatEmbeddedServletContainerFactory
|
|||
|
||||
private void onStart(Context context) {
|
||||
ServletContext servletContext = context.getServletContext();
|
||||
if (servletContext.getAttribute(this.MERGED_WEB_XML) == null) {
|
||||
servletContext.setAttribute(this.MERGED_WEB_XML, getEmptyWebXml());
|
||||
if (servletContext
|
||||
.getAttribute(StoreMergedWebXmlListener.MERGED_WEB_XML) == null) {
|
||||
servletContext.setAttribute(StoreMergedWebXmlListener.MERGED_WEB_XML,
|
||||
getEmptyWebXml());
|
||||
}
|
||||
TomcatResources.get(context).addClasspathResources();
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
|||
import org.springframework.beans.factory.support.BeanNameGenerator;
|
||||
import org.springframework.beans.factory.support.DefaultBeanNameGenerator;
|
||||
import org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext;
|
||||
import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationPreparedEvent;
|
||||
import org.springframework.boot.context.event.ApplicationReadyEvent;
|
||||
|
@ -971,8 +971,8 @@ public class SpringApplicationTests {
|
|||
static class ExampleWebConfig {
|
||||
|
||||
@Bean
|
||||
public JettyEmbeddedServletContainerFactory container() {
|
||||
return new JettyEmbeddedServletContainerFactory(0);
|
||||
public TomcatEmbeddedServletContainerFactory container() {
|
||||
return new TomcatEmbeddedServletContainerFactory(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -55,6 +55,7 @@ import javax.servlet.ServletResponse;
|
|||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.entity.InputStreamFactory;
|
||||
import org.apache.http.client.protocol.HttpClientContext;
|
||||
|
@ -124,6 +125,8 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
@BeforeClass
|
||||
@AfterClass
|
||||
public static void uninstallUrlStreamHandlerFactory() {
|
||||
ReflectionTestUtils.setField(TomcatURLStreamHandlerFactory.class, "instance",
|
||||
null);
|
||||
ReflectionTestUtils.setField(URL.class, "factory", null);
|
||||
}
|
||||
|
||||
|
@ -589,7 +592,7 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
|||
assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
|
||||
}
|
||||
|
||||
private Ssl getSsl(ClientAuth clientAuth, String keyPassword, String keyStore) {
|
||||
protected Ssl getSsl(ClientAuth clientAuth, String keyPassword, String keyStore) {
|
||||
return getSsl(clientAuth, keyPassword, keyStore, null, null, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ import org.apache.catalina.Wrapper;
|
|||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.valves.RemoteIpValve;
|
||||
import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
|
||||
import org.apache.tomcat.util.net.SSLHostConfig;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
|
@ -266,16 +266,14 @@ public class TomcatEmbeddedServletContainerFactoryTests
|
|||
Tomcat tomcat = getTomcat(factory);
|
||||
Connector connector = tomcat.getConnector();
|
||||
|
||||
AbstractHttp11JsseProtocol<?> jsseProtocol = (AbstractHttp11JsseProtocol<?>) connector
|
||||
.getProtocolHandler();
|
||||
assertThat(jsseProtocol.getCiphers()).isEqualTo("ALPHA,BRAVO,CHARLIE");
|
||||
SSLHostConfig[] sslHostConfigs = connector.getProtocolHandler()
|
||||
.findSslHostConfigs();
|
||||
assertThat(sslHostConfigs[0].getCiphers()).isEqualTo("ALPHA:BRAVO:CHARLIE");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslEnabledMultipleProtocolsConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
Ssl ssl = getSsl(null, "password", "src/test/resources/test.jks");
|
||||
ssl.setEnabledProtocols(new String[] { "TLSv1.1", "TLSv1.2" });
|
||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||
|
||||
|
@ -284,21 +282,20 @@ public class TomcatEmbeddedServletContainerFactoryTests
|
|||
|
||||
this.container = factory
|
||||
.getEmbeddedServletContainer(sessionServletRegistration());
|
||||
this.container.start();
|
||||
Tomcat tomcat = ((TomcatEmbeddedServletContainer) this.container).getTomcat();
|
||||
Connector connector = tomcat.getConnector();
|
||||
|
||||
AbstractHttp11JsseProtocol<?> jsseProtocol = (AbstractHttp11JsseProtocol<?>) connector
|
||||
.getProtocolHandler();
|
||||
assertThat(jsseProtocol.getSslProtocol()).isEqualTo("TLS");
|
||||
assertThat(jsseProtocol.getProperty("sslEnabledProtocols"))
|
||||
.isEqualTo("TLSv1.1,TLSv1.2");
|
||||
SSLHostConfig sslHostConfig = connector.getProtocolHandler()
|
||||
.findSslHostConfigs()[0];
|
||||
assertThat(sslHostConfig.getSslProtocol()).isEqualTo("TLS");
|
||||
assertThat(sslHostConfig.getEnabledProtocols())
|
||||
.containsExactlyInAnyOrder("TLSv1.1", "TLSv1.2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslEnabledProtocolsConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
Ssl ssl = getSsl(null, "password", "src/test/resources/test.jks");
|
||||
ssl.setEnabledProtocols(new String[] { "TLSv1.2" });
|
||||
ssl.setCiphers(new String[] { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "BRAVO" });
|
||||
|
||||
|
@ -310,10 +307,11 @@ public class TomcatEmbeddedServletContainerFactoryTests
|
|||
Tomcat tomcat = ((TomcatEmbeddedServletContainer) this.container).getTomcat();
|
||||
Connector connector = tomcat.getConnector();
|
||||
|
||||
AbstractHttp11JsseProtocol<?> jsseProtocol = (AbstractHttp11JsseProtocol<?>) connector
|
||||
.getProtocolHandler();
|
||||
assertThat(jsseProtocol.getSslProtocol()).isEqualTo("TLS");
|
||||
assertThat(jsseProtocol.getProperty("sslEnabledProtocols")).isEqualTo("TLSv1.2");
|
||||
this.container.start();
|
||||
SSLHostConfig sslHostConfig = connector.getProtocolHandler()
|
||||
.findSslHostConfigs()[0];
|
||||
assertThat(sslHostConfig.getSslProtocol()).isEqualTo("TLS");
|
||||
assertThat(sslHostConfig.getEnabledProtocols()).containsExactly("TLSv1.2");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
Loading…
Reference in New Issue