mirror of
https://github.com/spring-projects/spring-boot.git
synced 2024-09-03 04:26:12 +08:00
Add support for configuring SSL declaratively
Both Tomcat and Jetty can now be configured to use SSL via the environment (typically application.properties or application.yml) Closes #1084
This commit is contained in:
parent
d26ecbef04
commit
0960908bd7
@ -33,6 +33,7 @@ import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletCont
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatConnectorCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
|
||||
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
|
||||
@ -46,6 +47,7 @@ import org.springframework.util.StringUtils;
|
||||
*
|
||||
* @author Dave Syer
|
||||
* @author Stephane Nicoll
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = false)
|
||||
public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
@ -58,6 +60,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
private String contextPath;
|
||||
|
||||
private Ssl ssl;
|
||||
|
||||
@NotNull
|
||||
private String servletPath = "/";
|
||||
|
||||
@ -131,6 +135,14 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
this.sessionTimeout = sessionTimeout;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
||||
public void setSsl(Ssl ssl) {
|
||||
this.ssl = ssl;
|
||||
}
|
||||
|
||||
public void setLoader(String value) {
|
||||
// no op to support Tomcat running as a traditional container (not embedded)
|
||||
}
|
||||
@ -149,12 +161,41 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
if (getSessionTimeout() != null) {
|
||||
container.setSessionTimeout(getSessionTimeout());
|
||||
}
|
||||
if (getSsl() != null) {
|
||||
container.setSsl(getSsl());
|
||||
}
|
||||
if (container instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
getTomcat()
|
||||
.customizeTomcat((TomcatEmbeddedServletContainerFactory) container);
|
||||
}
|
||||
}
|
||||
|
||||
public String[] getPathsArray(Collection<String> paths) {
|
||||
String[] result = new String[paths.size()];
|
||||
int i = 0;
|
||||
for (String path : paths) {
|
||||
result[i++] = getPath(path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String[] getPathsArray(String[] paths) {
|
||||
String[] result = new String[paths.length];
|
||||
int i = 0;
|
||||
for (String path : paths) {
|
||||
result[i++] = getPath(path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getPath(String path) {
|
||||
String prefix = getServletPrefix();
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return prefix + path;
|
||||
}
|
||||
|
||||
public static class Tomcat {
|
||||
|
||||
private String accessLogPattern;
|
||||
@ -313,31 +354,4 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public String[] getPathsArray(Collection<String> paths) {
|
||||
String[] result = new String[paths.size()];
|
||||
int i = 0;
|
||||
for (String path : paths) {
|
||||
result[i++] = getPath(path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String[] getPathsArray(String[] paths) {
|
||||
String[] result = new String[paths.length];
|
||||
int i = 0;
|
||||
for (String path : paths) {
|
||||
result[i++] = getPath(path);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public String getPath(String path) {
|
||||
String prefix = getServletPrefix();
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" + path;
|
||||
}
|
||||
return prefix + path;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -56,6 +56,14 @@ content into your application; rather pick only the properties that you need.
|
||||
server.session-timeout= # session timeout in seconds
|
||||
server.context-path= # the context path, defaults to '/'
|
||||
server.servlet-path= # the servlet path, defaults to '/'
|
||||
server.ssl.client-auth= # want or need
|
||||
server.ssl.key-alias=
|
||||
server.ssl.key-password=
|
||||
server.ssl.key-store=
|
||||
server.ssl.key-store-password=
|
||||
server.ssl.protocol=TLS
|
||||
server.ssl.trust-store=
|
||||
server.ssl.trust-store-password=
|
||||
server.tomcat.access-log-pattern= # log pattern of the access log
|
||||
server.tomcat.access-log-enabled=false # is access logging enabled
|
||||
server.tomcat.protocol-header=x-forwarded-proto # ssl forward headers
|
||||
|
@ -387,6 +387,25 @@ and then inject the actual (``local'') port as a `@Value`. For example:
|
||||
}
|
||||
----
|
||||
|
||||
[[howto-configure-ssl]]
|
||||
=== Configure SSL
|
||||
SSL can be configured declaratively by setting the various `server.ssl.*` properties,
|
||||
typically in `application.properties` or `application.yml`. For example:
|
||||
|
||||
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
server.port = 8443
|
||||
server.ssl.key-store = classpath:keystore.jks
|
||||
server.ssl.key-store-password = secret
|
||||
server.ssl.key-password = another-secret
|
||||
----
|
||||
|
||||
See {sc-spring-boot}/context/embedded/Ssl.{sc-ext}[`Ssl`] for details of all of the
|
||||
supported properties.
|
||||
|
||||
NOTE: Tomcat requires the key store (and trust store if you're using one) to be directly
|
||||
accessible on the filesystem, i.e. it cannot be read from within a jar file.
|
||||
|
||||
|
||||
|
||||
[[howto-configure-tomcat]]
|
||||
@ -401,56 +420,6 @@ nuclear option is to add your own `TomcatEmbeddedServletContainerFactory`.
|
||||
|
||||
|
||||
|
||||
[[howto-terminate-ssl-in-tomcat]]
|
||||
=== Terminate SSL in Tomcat
|
||||
Use an `EmbeddedServletContainerCustomizer` and in that add a `TomcatConnectorCustomizer`
|
||||
that sets up the connector to be secure:
|
||||
|
||||
[source,java,indent=0,subs="verbatim,quotes,attributes"]
|
||||
----
|
||||
@Bean
|
||||
public EmbeddedServletContainerCustomizer containerCustomizer(){
|
||||
return new MyCustomizer();
|
||||
}
|
||||
|
||||
// ...
|
||||
|
||||
private static class MyCustomizer implements EmbeddedServletContainerCustomizer {
|
||||
|
||||
@Override
|
||||
public void customize(ConfigurableEmbeddedServletContainer factory) {
|
||||
if(factory instanceof TomcatEmbeddedServletContainerFactory) {
|
||||
customizeTomcat((TomcatEmbeddedServletContainerFactory) factory));
|
||||
}
|
||||
}
|
||||
|
||||
public void customizeTomcat(TomcatEmbeddedServletContainerFactory factory) {
|
||||
factory.addConnectorCustomizers(new TomcatConnectorCustomizer() {
|
||||
@Override
|
||||
public void customize(Connector connector) {
|
||||
connector.setPort(serverPort);
|
||||
connector.setSecure(true);
|
||||
connector.setScheme("https");
|
||||
connector.setAttribute("keyAlias", "tomcat");
|
||||
connector.setAttribute("keystorePass", "password");
|
||||
try {
|
||||
connector.setAttribute("keystoreFile",
|
||||
ResourceUtils.getFile("src/ssl/tomcat.keystore").getAbsolutePath());
|
||||
} catch (FileNotFoundException e) {
|
||||
throw new IllegalStateException("Cannot load keystore", e);
|
||||
}
|
||||
connector.setAttribute("clientAuth", "false");
|
||||
connector.setAttribute("sslProtocol", "TLS");
|
||||
connector.setAttribute("SSLEnabled", true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
|
||||
|
||||
[[howto-enable-multiple-connectors-in-tomcat]]
|
||||
=== Enable Multiple Connectors Tomcat
|
||||
Add a `org.apache.catalina.connector.Connector` to the
|
||||
|
@ -44,6 +44,7 @@
|
||||
<module>spring-boot-sample-secure</module>
|
||||
<module>spring-boot-sample-servlet</module>
|
||||
<module>spring-boot-sample-simple</module>
|
||||
<module>spring-boot-sample-tomcat-ssl</module>
|
||||
<module>spring-boot-sample-tomcat</module>
|
||||
<module>spring-boot-sample-tomcat-multi-connectors</module>
|
||||
<module>spring-boot-sample-tomcat8-jsp</module>
|
||||
|
56
spring-boot-samples/spring-boot-sample-tomcat-ssl/pom.xml
Normal file
56
spring-boot-samples/spring-boot-sample-tomcat-ssl/pom.xml
Normal file
@ -0,0 +1,56 @@
|
||||
<?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.2.0.BUILD-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>spring-boot-sample-tomcat-ssl</artifactId>
|
||||
<name>Spring Boot Tomcat Sample</name>
|
||||
<description>Spring Boot Tomcat 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>
|
||||
</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>
|
BIN
spring-boot-samples/spring-boot-sample-tomcat-ssl/sample.jks
Normal file
BIN
spring-boot-samples/spring-boot-sample-tomcat-ssl/sample.jks
Normal file
Binary file not shown.
@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@ComponentScan
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@EnableConfigurationProperties
|
||||
public class SampleTomcatSslApplication {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(SampleTomcatSslApplication.class, args);
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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.web;
|
||||
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
|
||||
@Controller
|
||||
public class SampleController {
|
||||
|
||||
@RequestMapping("/")
|
||||
@ResponseBody
|
||||
public String helloWorld() {
|
||||
return "Hello, world";
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,4 @@
|
||||
server.port = 8443
|
||||
server.ssl.key-store = sample.jks
|
||||
server.ssl.key-store-password = secret
|
||||
server.ssl.key-password = password
|
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.boot.test.IntegrationTest;
|
||||
import org.springframework.boot.test.SpringApplicationConfiguration;
|
||||
import org.springframework.boot.test.TestRestTemplate;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.web.WebAppConfiguration;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@SpringApplicationConfiguration(classes = SampleTomcatSslApplication.class)
|
||||
@WebAppConfiguration
|
||||
@IntegrationTest("server.port:0")
|
||||
@DirtiesContext
|
||||
public class SampleTomcatSslApplicationTests {
|
||||
|
||||
@Value("${local.server.port}")
|
||||
private int port;
|
||||
|
||||
@Test
|
||||
public void testHome() throws Exception {
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null,
|
||||
new TrustSelfSignedStrategy()).build());
|
||||
|
||||
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
|
||||
.build();
|
||||
|
||||
TestRestTemplate testRestTemplate = new TestRestTemplate();
|
||||
((HttpComponentsClientHttpRequestFactory) testRestTemplate.getRequestFactory())
|
||||
.setHttpClient(httpClient);
|
||||
ResponseEntity<String> entity = testRestTemplate.getForEntity(
|
||||
"https://localhost:" + this.port, String.class);
|
||||
assertEquals(HttpStatus.OK, entity.getStatusCode());
|
||||
assertEquals("Hello, world", entity.getBody());
|
||||
}
|
||||
}
|
@ -59,6 +59,8 @@ public abstract class AbstractConfigurableEmbeddedServletContainer implements
|
||||
|
||||
private int sessionTimeout;
|
||||
|
||||
private Ssl ssl;
|
||||
|
||||
/**
|
||||
* Create a new {@link AbstractConfigurableEmbeddedServletContainer} instance.
|
||||
*/
|
||||
@ -247,6 +249,15 @@ public abstract class AbstractConfigurableEmbeddedServletContainer implements
|
||||
this.jspServletClassName = jspServletClassName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setSsl(Ssl ssl) {
|
||||
this.ssl = ssl;
|
||||
}
|
||||
|
||||
public Ssl getSsl() {
|
||||
return this.ssl;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the JSP servlet class name
|
||||
*/
|
||||
|
@ -139,4 +139,10 @@ public interface ConfigurableEmbeddedServletContainer {
|
||||
*/
|
||||
void addInitializers(ServletContextInitializer... initializers);
|
||||
|
||||
/**
|
||||
* Sets the SSL configuration that will be applied to the container's default
|
||||
* connector.
|
||||
* @param ssl the SSL configuration
|
||||
*/
|
||||
void setSsl(Ssl ssl);
|
||||
}
|
||||
|
@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright 2012-2014 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;
|
||||
|
||||
/**
|
||||
* Simple container-independent abstraction for SSL configuration.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
* @since 1.2.0
|
||||
*/
|
||||
public class Ssl {
|
||||
|
||||
private ClientAuth clientAuth;
|
||||
|
||||
private String[] ciphers;
|
||||
|
||||
private String keyAlias;
|
||||
|
||||
private String keyPassword;
|
||||
|
||||
private String keyStore;
|
||||
|
||||
private String keyStorePassword;
|
||||
|
||||
private String trustStore;
|
||||
|
||||
private String trustStorePassword;
|
||||
|
||||
private String protocol = "TLS";
|
||||
|
||||
public ClientAuth getClientAuth() {
|
||||
return this.clientAuth;
|
||||
}
|
||||
|
||||
public void setClientAuth(ClientAuth clientAuth) {
|
||||
this.clientAuth = clientAuth;
|
||||
}
|
||||
|
||||
public String[] getCiphers() {
|
||||
return this.ciphers;
|
||||
}
|
||||
|
||||
public void setCiphers(String[] ciphers) {
|
||||
this.ciphers = ciphers;
|
||||
}
|
||||
|
||||
public String getKeyAlias() {
|
||||
return this.keyAlias;
|
||||
}
|
||||
|
||||
public void setKeyAlias(String keyAlias) {
|
||||
this.keyAlias = keyAlias;
|
||||
}
|
||||
|
||||
public String getKeyPassword() {
|
||||
return this.keyPassword;
|
||||
}
|
||||
|
||||
public void setKeyPassword(String keyPassword) {
|
||||
this.keyPassword = keyPassword;
|
||||
}
|
||||
|
||||
public String getKeyStore() {
|
||||
return this.keyStore;
|
||||
}
|
||||
|
||||
public void setKeyStore(String keyStore) {
|
||||
this.keyStore = keyStore;
|
||||
}
|
||||
|
||||
public String getKeyStorePassword() {
|
||||
return this.keyStorePassword;
|
||||
}
|
||||
|
||||
public void setKeyStorePassword(String keyStorePassword) {
|
||||
this.keyStorePassword = keyStorePassword;
|
||||
}
|
||||
|
||||
public String getTrustStore() {
|
||||
return this.trustStore;
|
||||
}
|
||||
|
||||
public void setTrustStore(String trustStore) {
|
||||
this.trustStore = trustStore;
|
||||
}
|
||||
|
||||
public String getTrustStorePassword() {
|
||||
return this.trustStorePassword;
|
||||
}
|
||||
|
||||
public void setTrustStorePassword(String trustStorePassword) {
|
||||
this.trustStorePassword = trustStorePassword;
|
||||
}
|
||||
|
||||
public String getProtocol() {
|
||||
return this.protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public enum ClientAuth {
|
||||
WANT, NEED;
|
||||
}
|
||||
}
|
@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.context.embedded.jetty;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@ -24,25 +25,32 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jetty.http.MimeTypes;
|
||||
import org.eclipse.jetty.server.Connector;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.handler.ErrorHandler;
|
||||
import org.eclipse.jetty.server.ssl.SslSocketConnector;
|
||||
import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
|
||||
import org.eclipse.jetty.servlet.ServletHolder;
|
||||
import org.eclipse.jetty.servlet.ServletMapping;
|
||||
import org.eclipse.jetty.util.resource.Resource;
|
||||
import org.eclipse.jetty.util.ssl.SslContextFactory;
|
||||
import org.eclipse.jetty.webapp.AbstractConfiguration;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerException;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.ErrorPage;
|
||||
import org.springframework.boot.context.embedded.MimeMappings;
|
||||
import org.springframework.boot.context.embedded.ServletContextInitializer;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.boot.context.embedded.Ssl.ClientAuth;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
@ -104,6 +112,16 @@ public class JettyEmbeddedServletContainerFactory extends
|
||||
configureWebAppContext(context, initializers);
|
||||
server.setHandler(context);
|
||||
this.logger.info("Server initialized with port: " + port);
|
||||
|
||||
if (getSsl() != null) {
|
||||
SslContextFactory sslContextFactory = new SslContextFactory();
|
||||
configureSslContextFactory(sslContextFactory, getSsl());
|
||||
|
||||
SslSocketConnector sslConnector = new SslSocketConnector(sslContextFactory);
|
||||
sslConnector.setPort(port);
|
||||
server.setConnectors(new Connector[] { sslConnector });
|
||||
}
|
||||
|
||||
for (JettyServerCustomizer customizer : getServerCustomizers()) {
|
||||
customizer.customize(server);
|
||||
}
|
||||
@ -111,6 +129,52 @@ public class JettyEmbeddedServletContainerFactory extends
|
||||
return getJettyEmbeddedServletContainer(server);
|
||||
}
|
||||
|
||||
protected void configureSslContextFactory(SslContextFactory sslContextFactory, Ssl ssl) {
|
||||
sslContextFactory.setProtocol(getSsl().getProtocol());
|
||||
if (getSsl().getClientAuth() == ClientAuth.NEED) {
|
||||
sslContextFactory.setNeedClientAuth(true);
|
||||
sslContextFactory.setWantClientAuth(true);
|
||||
}
|
||||
else if (getSsl().getClientAuth() == ClientAuth.WANT) {
|
||||
sslContextFactory.setWantClientAuth(true);
|
||||
}
|
||||
if (getSsl().getKeyStorePassword() != null) {
|
||||
sslContextFactory.setKeyStorePassword(getSsl().getKeyStorePassword());
|
||||
}
|
||||
if (getSsl().getKeyPassword() != null) {
|
||||
sslContextFactory.setKeyManagerPassword(getSsl().getKeyPassword());
|
||||
}
|
||||
sslContextFactory.setCertAlias(getSsl().getKeyAlias());
|
||||
try {
|
||||
sslContextFactory.setKeyStoreResource(Resource.newResource(ResourceUtils
|
||||
.getURL(getSsl().getKeyStore())));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new EmbeddedServletContainerException("Could not find key store '"
|
||||
+ getSsl().getKeyStore() + "'", e);
|
||||
}
|
||||
|
||||
if (getSsl().getCiphers() != null) {
|
||||
sslContextFactory.setIncludeCipherSuites(getSsl().getCiphers());
|
||||
}
|
||||
|
||||
if (getSsl().getTrustStorePassword() != null) {
|
||||
sslContextFactory.setTrustStorePassword(getSsl().getTrustStorePassword());
|
||||
}
|
||||
|
||||
if (getSsl().getTrustStore() != null) {
|
||||
try {
|
||||
sslContextFactory.setTrustStoreResource(Resource
|
||||
.newResource(ResourceUtils.getURL(getSsl().getTrustStore())));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new EmbeddedServletContainerException(
|
||||
"Could not find trust store '" + getSsl().getTrustStore() + "'",
|
||||
e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the given Jetty {@link WebAppContext} for use.
|
||||
* @param context the context to configure
|
||||
|
@ -17,6 +17,7 @@
|
||||
package org.springframework.boot.context.embedded.tomcat;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
@ -41,6 +42,7 @@ import org.apache.catalina.loader.WebappLoader;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.catalina.startup.Tomcat.FixContextListener;
|
||||
import org.apache.coyote.AbstractProtocol;
|
||||
import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactory;
|
||||
import org.springframework.boot.context.embedded.EmbeddedServletContainer;
|
||||
@ -49,12 +51,16 @@ import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory
|
||||
import org.springframework.boot.context.embedded.ErrorPage;
|
||||
import org.springframework.boot.context.embedded.MimeMappings;
|
||||
import org.springframework.boot.context.embedded.ServletContextInitializer;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.boot.context.embedded.Ssl.ClientAuth;
|
||||
import org.springframework.context.ResourceLoaderAware;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
import org.springframework.util.StreamUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link EmbeddedServletContainerFactory} that can be used to create
|
||||
@ -230,11 +236,64 @@ public class TomcatEmbeddedServletContainerFactory extends
|
||||
// If ApplicationContext is slow to start we want Tomcat not to bind to the socket
|
||||
// prematurely...
|
||||
connector.setProperty("bindOnInit", "false");
|
||||
|
||||
if (getSsl() != null) {
|
||||
if (connector.getProtocolHandler() instanceof AbstractHttp11JsseProtocol) {
|
||||
AbstractHttp11JsseProtocol jsseProtocol = (AbstractHttp11JsseProtocol) connector
|
||||
.getProtocolHandler();
|
||||
configureJsseProtocol(jsseProtocol, getSsl());
|
||||
connector.setScheme("https");
|
||||
connector.setSecure(true);
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException(
|
||||
"To use SSL, the connector's protocol handler must be an AbstractHttp11JsseProtocol subclass");
|
||||
}
|
||||
}
|
||||
|
||||
for (TomcatConnectorCustomizer customizer : this.tomcatConnectorCustomizers) {
|
||||
customizer.customize(connector);
|
||||
}
|
||||
}
|
||||
|
||||
protected void configureJsseProtocol(AbstractHttp11JsseProtocol jsseProtocol, Ssl ssl) {
|
||||
jsseProtocol.setSSLEnabled(true);
|
||||
jsseProtocol.setSslProtocol(getSsl().getProtocol());
|
||||
if (getSsl().getClientAuth() == ClientAuth.NEED) {
|
||||
jsseProtocol.setClientAuth(Boolean.TRUE.toString());
|
||||
}
|
||||
else if (getSsl().getClientAuth() == ClientAuth.WANT) {
|
||||
jsseProtocol.setClientAuth("want");
|
||||
}
|
||||
jsseProtocol.setKeystorePass(getSsl().getKeyStorePassword());
|
||||
jsseProtocol.setKeyPass(getSsl().getKeyPassword());
|
||||
jsseProtocol.setKeyAlias(getSsl().getKeyAlias());
|
||||
try {
|
||||
jsseProtocol.setKeystoreFile(ResourceUtils.getFile(getSsl().getKeyStore())
|
||||
.getAbsolutePath());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
throw new EmbeddedServletContainerException("Could not find key store "
|
||||
+ getSsl().getKeyStore(), e);
|
||||
}
|
||||
|
||||
jsseProtocol.setCiphers(StringUtils.arrayToCommaDelimitedString(getSsl()
|
||||
.getCiphers()));
|
||||
|
||||
if (getSsl().getTrustStore() != null) {
|
||||
try {
|
||||
jsseProtocol.setTruststoreFile(ResourceUtils.getFile(
|
||||
getSsl().getTrustStore()).getAbsolutePath());
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
throw new EmbeddedServletContainerException("Could not find trust store "
|
||||
+ getSsl().getTrustStore(), e);
|
||||
}
|
||||
}
|
||||
|
||||
jsseProtocol.setTruststorePass(getSsl().getTrustStorePassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure the Tomcat {@link Context}.
|
||||
* @param context the Tomcat context
|
||||
|
@ -16,11 +16,14 @@
|
||||
|
||||
package org.springframework.boot.context.embedded;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.Charset;
|
||||
import java.security.KeyStore;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
@ -31,12 +34,18 @@ import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||
import org.apache.http.conn.ssl.SSLContextBuilder;
|
||||
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
|
||||
import org.apache.http.impl.client.HttpClients;
|
||||
import org.junit.After;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
import org.mockito.InOrder;
|
||||
import org.springframework.boot.context.embedded.Ssl.ClientAuth;
|
||||
import org.springframework.http.HttpMethod;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.client.ClientHttpRequest;
|
||||
@ -62,6 +71,7 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Greg Turnquist
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
|
||||
@ -300,8 +310,192 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
assertThat(getResponse(getLocalUrl("/bang")), equalTo("Hello World"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void basicSsl() throws Exception {
|
||||
FileCopyUtils.copy("test",
|
||||
new FileWriter(this.temporaryFolder.newFile("test.txt")));
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setDocumentRoot(this.temporaryFolder.getRoot());
|
||||
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
factory.setSsl(ssl);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
this.container.start();
|
||||
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null,
|
||||
new TrustSelfSignedStrategy()).build());
|
||||
|
||||
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
|
||||
.build();
|
||||
|
||||
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClient);
|
||||
|
||||
assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory),
|
||||
equalTo("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslNeedsClientAuthenticationSucceedsWithClientCertificate()
|
||||
throws Exception {
|
||||
FileCopyUtils.copy("test",
|
||||
new FileWriter(this.temporaryFolder.newFile("test.txt")));
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setDocumentRoot(this.temporaryFolder.getRoot());
|
||||
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setClientAuth(ClientAuth.NEED);
|
||||
ssl.setTrustStore("src/test/resources/test.jks");
|
||||
ssl.setTrustStorePassword("secret");
|
||||
factory.setSsl(ssl);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
this.container.start();
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(new FileInputStream(new File("src/test/resources/test.jks")),
|
||||
"secret".toCharArray());
|
||||
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder()
|
||||
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "password".toCharArray()).build());
|
||||
|
||||
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
|
||||
.build();
|
||||
|
||||
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClient);
|
||||
|
||||
assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory),
|
||||
equalTo("test"));
|
||||
}
|
||||
|
||||
@Test(expected = IOException.class)
|
||||
public void sslNeedsClientAuthenticationFailsWithoutClientCertificate()
|
||||
throws Exception {
|
||||
FileCopyUtils.copy("test",
|
||||
new FileWriter(this.temporaryFolder.newFile("test.txt")));
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setDocumentRoot(this.temporaryFolder.getRoot());
|
||||
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setClientAuth(ClientAuth.NEED);
|
||||
ssl.setTrustStore("src/test/resources/test.jks");
|
||||
ssl.setTrustStorePassword("secret");
|
||||
factory.setSsl(ssl);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
this.container.start();
|
||||
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null,
|
||||
new TrustSelfSignedStrategy()).build());
|
||||
|
||||
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
|
||||
.build();
|
||||
|
||||
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClient);
|
||||
|
||||
getResponse(getLocalUrl("https", "/test.txt"), requestFactory);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslWantsClientAuthenticationSucceedsWithClientCertificate()
|
||||
throws Exception {
|
||||
FileCopyUtils.copy("test",
|
||||
new FileWriter(this.temporaryFolder.newFile("test.txt")));
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setDocumentRoot(this.temporaryFolder.getRoot());
|
||||
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setClientAuth(ClientAuth.WANT);
|
||||
ssl.setTrustStore("src/test/resources/test.jks");
|
||||
ssl.setTrustStorePassword("secret");
|
||||
factory.setSsl(ssl);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
this.container.start();
|
||||
|
||||
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
|
||||
keyStore.load(new FileInputStream(new File("src/test/resources/test.jks")),
|
||||
"secret".toCharArray());
|
||||
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder()
|
||||
.loadTrustMaterial(null, new TrustSelfSignedStrategy())
|
||||
.loadKeyMaterial(keyStore, "password".toCharArray()).build());
|
||||
|
||||
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
|
||||
.build();
|
||||
|
||||
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClient);
|
||||
|
||||
assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory),
|
||||
equalTo("test"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslWantsClientAuthenticationSucceedsWithoutClientCertificate()
|
||||
throws Exception {
|
||||
FileCopyUtils.copy("test",
|
||||
new FileWriter(this.temporaryFolder.newFile("test.txt")));
|
||||
|
||||
AbstractEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setDocumentRoot(this.temporaryFolder.getRoot());
|
||||
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setClientAuth(ClientAuth.WANT);
|
||||
ssl.setTrustStore("src/test/resources/test.jks");
|
||||
ssl.setTrustStorePassword("secret");
|
||||
factory.setSsl(ssl);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
this.container.start();
|
||||
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(
|
||||
new SSLContextBuilder().loadTrustMaterial(null,
|
||||
new TrustSelfSignedStrategy()).build());
|
||||
|
||||
HttpClient httpClient = HttpClients.custom().setSSLSocketFactory(socketFactory)
|
||||
.build();
|
||||
|
||||
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(
|
||||
httpClient);
|
||||
|
||||
assertThat(getResponse(getLocalUrl("https", "/test.txt"), requestFactory),
|
||||
equalTo("test"));
|
||||
}
|
||||
|
||||
protected String getLocalUrl(String resourcePath) {
|
||||
return "http://localhost:" + this.container.getPort() + resourcePath;
|
||||
return getLocalUrl("http", resourcePath);
|
||||
}
|
||||
|
||||
protected String getLocalUrl(String scheme, String resourcePath) {
|
||||
return scheme + "://localhost:" + this.container.getPort() + resourcePath;
|
||||
}
|
||||
|
||||
protected String getLocalUrl(int port, String resourcePath) {
|
||||
@ -318,10 +512,27 @@ public abstract class AbstractEmbeddedServletContainerFactoryTests {
|
||||
}
|
||||
}
|
||||
|
||||
protected String getResponse(String url,
|
||||
HttpComponentsClientHttpRequestFactory requestFactory) throws IOException,
|
||||
URISyntaxException {
|
||||
ClientHttpResponse response = getClientResponse(url, requestFactory);
|
||||
try {
|
||||
return StreamUtils.copyToString(response.getBody(), Charset.forName("UTF-8"));
|
||||
}
|
||||
finally {
|
||||
response.close();
|
||||
}
|
||||
}
|
||||
|
||||
protected ClientHttpResponse getClientResponse(String url) throws IOException,
|
||||
URISyntaxException {
|
||||
HttpComponentsClientHttpRequestFactory clientHttpRequestFactory = new HttpComponentsClientHttpRequestFactory();
|
||||
ClientHttpRequest request = clientHttpRequestFactory.createRequest(new URI(url),
|
||||
return getClientResponse(url, new HttpComponentsClientHttpRequestFactory());
|
||||
}
|
||||
|
||||
protected ClientHttpResponse getClientResponse(String url,
|
||||
HttpComponentsClientHttpRequestFactory requestFactory) throws IOException,
|
||||
URISyntaxException {
|
||||
ClientHttpRequest request = requestFactory.createRequest(new URI(url),
|
||||
HttpMethod.GET);
|
||||
ClientHttpResponse response = request.execute();
|
||||
return response;
|
||||
|
@ -21,11 +21,13 @@ import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.jetty.server.Handler;
|
||||
import org.eclipse.jetty.server.Server;
|
||||
import org.eclipse.jetty.server.ssl.SslConnector;
|
||||
import org.eclipse.jetty.webapp.Configuration;
|
||||
import org.eclipse.jetty.webapp.WebAppContext;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@ -39,6 +41,7 @@ import static org.mockito.Mockito.mock;
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Dave Syer
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class JettyEmbeddedServletContainerFactoryTests extends
|
||||
AbstractEmbeddedServletContainerFactoryTests {
|
||||
@ -94,6 +97,25 @@ public class JettyEmbeddedServletContainerFactoryTests extends
|
||||
assertTimeout(factory, 60);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslCiphersConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("src/test/resources/test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setKeyPassword("password");
|
||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||
|
||||
JettyEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setSsl(ssl);
|
||||
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
JettyEmbeddedServletContainer jettyContainer = (JettyEmbeddedServletContainer) this.container;
|
||||
SslConnector sslConnector = (SslConnector) jettyContainer.getServer()
|
||||
.getConnectors()[0];
|
||||
assertThat(sslConnector.getSslContextFactory().getIncludeCipherSuites(),
|
||||
equalTo(new String[] { "ALPHA", "BRAVO", "CHARLIE" }));
|
||||
}
|
||||
|
||||
private void assertTimeout(JettyEmbeddedServletContainerFactory factory, int expected) {
|
||||
this.container = factory.getEmbeddedServletContainer();
|
||||
JettyEmbeddedServletContainer jettyContainer = (JettyEmbeddedServletContainer) this.container;
|
||||
|
@ -28,9 +28,11 @@ import org.apache.catalina.Service;
|
||||
import org.apache.catalina.Valve;
|
||||
import org.apache.catalina.connector.Connector;
|
||||
import org.apache.catalina.startup.Tomcat;
|
||||
import org.apache.coyote.http11.AbstractHttp11JsseProtocol;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
import org.springframework.boot.context.embedded.AbstractEmbeddedServletContainerFactoryTests;
|
||||
import org.springframework.boot.context.embedded.Ssl;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
@ -221,6 +223,24 @@ public class TomcatEmbeddedServletContainerFactoryTests extends
|
||||
assertEquals("UTF-8", tomcat.getConnector().getURIEncoding());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sslCiphersConfiguration() throws Exception {
|
||||
Ssl ssl = new Ssl();
|
||||
ssl.setKeyStore("test.jks");
|
||||
ssl.setKeyStorePassword("secret");
|
||||
ssl.setCiphers(new String[] { "ALPHA", "BRAVO", "CHARLIE" });
|
||||
|
||||
TomcatEmbeddedServletContainerFactory factory = getFactory();
|
||||
factory.setSsl(ssl);
|
||||
|
||||
Tomcat tomcat = getTomcat(factory);
|
||||
Connector connector = tomcat.getConnector();
|
||||
|
||||
AbstractHttp11JsseProtocol jsseProtocol = (AbstractHttp11JsseProtocol) connector
|
||||
.getProtocolHandler();
|
||||
assertThat(jsseProtocol.getCiphers(), equalTo("ALPHA,BRAVO,CHARLIE"));
|
||||
}
|
||||
|
||||
private void assertTimeout(TomcatEmbeddedServletContainerFactory factory, int expected) {
|
||||
Tomcat tomcat = getTomcat(factory);
|
||||
Context context = (Context) tomcat.getHost().findChildren()[0];
|
||||
|
BIN
spring-boot/src/test/resources/test.jks
Normal file
BIN
spring-boot/src/test/resources/test.jks
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user