Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
62a5ce52
Commit
62a5ce52
authored
Sep 17, 2014
by
Phillip Webb
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Backport Jetty/Tomcat SSL support
Fixes gh-1570 Cherry-picked from
0960908b
and
258c6f11
parent
fae9ab41
Changes
20
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
20 changed files
with
920 additions
and
80 deletions
+920
-80
ServerProperties.java
...ingframework/boot/autoconfigure/web/ServerProperties.java
+40
-27
appendix-application-properties.adoc
...cs/src/main/asciidoc/appendix-application-properties.adoc
+12
-0
howto.adoc
spring-boot-docs/src/main/asciidoc/howto.adoc
+21
-50
pom.xml
spring-boot-samples/pom.xml
+1
-0
pom.xml
spring-boot-samples/spring-boot-sample-tomcat-ssl/pom.xml
+56
-0
sample.jks
spring-boot-samples/spring-boot-sample-tomcat-ssl/sample.jks
+0
-0
SampleTomcatSslApplication.java
...c/main/java/sample/tomcat/SampleTomcatSslApplication.java
+35
-0
SampleController.java
...ssl/src/main/java/sample/tomcat/web/SampleController.java
+32
-0
application.properties
...mple-tomcat-ssl/src/main/resources/application.properties
+4
-0
SampleTomcatSslApplicationTests.java
...t/java/sample/tomcat/SampleTomcatSslApplicationTests.java
+67
-0
AbstractConfigurableEmbeddedServletContainer.java
...mbedded/AbstractConfigurableEmbeddedServletContainer.java
+11
-0
ConfigurableEmbeddedServletContainer.java
...ontext/embedded/ConfigurableEmbeddedServletContainer.java
+7
-0
Ssl.java
...n/java/org/springframework/boot/context/embedded/Ssl.java
+160
-0
JettyEmbeddedServletContainerFactory.java
.../embedded/jetty/JettyEmbeddedServletContainerFactory.java
+94
-0
TomcatEmbeddedServletContainerFactory.java
...mbedded/tomcat/TomcatEmbeddedServletContainerFactory.java
+82
-0
AbstractEmbeddedServletContainerFactoryTests.java
...mbedded/AbstractEmbeddedServletContainerFactoryTests.java
+254
-3
JettyEmbeddedServletContainerFactoryTests.java
...dded/jetty/JettyEmbeddedServletContainerFactoryTests.java
+24
-0
TomcatEmbeddedServletContainerFactoryTests.java
...ed/tomcat/TomcatEmbeddedServletContainerFactoryTests.java
+20
-0
test.jks
spring-boot/src/test/resources/test.jks
+0
-0
test.p12
spring-boot/src/test/resources/test.p12
+0
-0
No files found.
spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/ServerProperties.java
View file @
62a5ce52
...
...
@@ -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
;
...
...
@@ -59,6 +60,8 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer {
private
String
contextPath
;
private
Ssl
ssl
;
@NotNull
private
String
servletPath
=
"/"
;
...
...
@@ -132,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)
}
...
...
@@ -150,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
;
...
...
@@ -330,31 +370,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
;
}
}
spring-boot-docs/src/main/asciidoc/appendix-application-properties.adoc
View file @
62a5ce52
...
...
@@ -56,6 +56,18 @@ 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.key-store-provider=
server.ssl.key-store-type=
server.ssl.protocol=TLS
server.ssl.trust-store=
server.ssl.trust-store-password=
server.ssl.trust-store-provider=
server.ssl.trust-store-type=
server.tomcat.access-log-pattern= # log pattern of the access log
server.tomcat.access-log-enabled=false # is access logging enabled
server.tomcat.internal-proxies=10\.\d{1,3}\.\d{1,3}\.\d{1,3}|\
...
...
spring-boot-docs/src/main/asciidoc/howto.adoc
View file @
62a5ce52
...
...
@@ -389,6 +389,27 @@ 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]]
=== Configure Tomcat
Generally you can follow the advice from
...
...
@@ -401,56 +422,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
...
...
spring-boot-samples/pom.xml
View file @
62a5ce52
...
...
@@ -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>
...
...
spring-boot-samples/spring-boot-sample-tomcat-ssl/pom.xml
0 → 100644
View file @
62a5ce52
<?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.1.7.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>
spring-boot-samples/spring-boot-sample-tomcat-ssl/sample.jks
0 → 100644
View file @
62a5ce52
File added
spring-boot-samples/spring-boot-sample-tomcat-ssl/src/main/java/sample/tomcat/SampleTomcatSslApplication.java
0 → 100644
View file @
62a5ce52
/*
* 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
);
}
}
spring-boot-samples/spring-boot-sample-tomcat-ssl/src/main/java/sample/tomcat/web/SampleController.java
0 → 100644
View file @
62a5ce52
/*
* 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"
;
}
}
spring-boot-samples/spring-boot-sample-tomcat-ssl/src/main/resources/application.properties
0 → 100644
View file @
62a5ce52
server.port
=
8443
server.ssl.key-store
=
sample.jks
server.ssl.key-store-password
=
secret
server.ssl.key-password
=
password
\ No newline at end of file
spring-boot-samples/spring-boot-sample-tomcat-ssl/src/test/java/sample/tomcat/SampleTomcatSslApplicationTests.java
0 → 100644
View file @
62a5ce52
/*
* 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
());
}
}
spring-boot/src/main/java/org/springframework/boot/context/embedded/AbstractConfigurableEmbeddedServletContainer.java
View file @
62a5ce52
...
...
@@ -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
*/
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/ConfigurableEmbeddedServletContainer.java
View file @
62a5ce52
...
...
@@ -139,4 +139,11 @@ 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
);
}
spring-boot/src/main/java/org/springframework/boot/context/embedded/Ssl.java
0 → 100644
View file @
62a5ce52
/*
* 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
keyStoreType
;
private
String
keyStoreProvider
;
private
String
trustStore
;
private
String
trustStorePassword
;
private
String
trustStoreType
;
private
String
trustStoreProvider
;
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
getKeyStoreType
()
{
return
this
.
keyStoreType
;
}
public
void
setKeyStoreType
(
String
keyStoreType
)
{
this
.
keyStoreType
=
keyStoreType
;
}
public
String
getKeyStoreProvider
()
{
return
this
.
keyStoreProvider
;
}
public
void
setKeyStoreProvider
(
String
keyStoreProvider
)
{
this
.
keyStoreProvider
=
keyStoreProvider
;
}
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
getTrustStoreType
()
{
return
this
.
trustStoreType
;
}
public
void
setTrustStoreType
(
String
trustStoreType
)
{
this
.
trustStoreType
=
trustStoreType
;
}
public
String
getTrustStoreProvider
()
{
return
this
.
trustStoreProvider
;
}
public
void
setTrustStoreProvider
(
String
trustStoreProvider
)
{
this
.
trustStoreProvider
=
trustStoreProvider
;
}
public
String
getProtocol
()
{
return
this
.
protocol
;
}
public
void
setProtocol
(
String
protocol
)
{
this
.
protocol
=
protocol
;
}
public
enum
ClientAuth
{
WANT
,
NEED
;
}
}
spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java
View file @
62a5ce52
...
...
@@ -17,32 +17,41 @@
package
org
.
springframework
.
boot
.
context
.
embedded
.
jetty
;
import
java.io.File
;
import
java.io.IOException
;
import
java.net.InetSocketAddress
;
import
java.net.URL
;
import
java.util.ArrayList
;
import
java.util.Arrays
;
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 +113,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
();
configureSsl
(
sslContextFactory
,
getSsl
());
SslSocketConnector
sslConnector
=
new
SslSocketConnector
(
sslContextFactory
);
sslConnector
.
setPort
(
port
);
server
.
setConnectors
(
new
Connector
[]
{
sslConnector
});
}
for
(
JettyServerCustomizer
customizer
:
getServerCustomizers
())
{
customizer
.
customize
(
server
);
}
...
...
@@ -111,6 +130,81 @@ public class JettyEmbeddedServletContainerFactory extends
return
getJettyEmbeddedServletContainer
(
server
);
}
/**
* Configure the SSL connection.
* @param factory the Jetty {@link SslContextFactory}.
* @param ssl the ssl details.
*/
protected
void
configureSsl
(
SslContextFactory
factory
,
Ssl
ssl
)
{
factory
.
setProtocol
(
ssl
.
getProtocol
());
configureSslClientAuth
(
factory
,
ssl
);
configureSslPasswords
(
factory
,
ssl
);
factory
.
setCertAlias
(
ssl
.
getKeyAlias
());
configureSslKeyStore
(
factory
,
ssl
);
if
(
ssl
.
getCiphers
()
!=
null
)
{
factory
.
setIncludeCipherSuites
(
ssl
.
getCiphers
());
}
configureSslTrustStore
(
factory
,
ssl
);
}
private
void
configureSslClientAuth
(
SslContextFactory
factory
,
Ssl
ssl
)
{
if
(
ssl
.
getClientAuth
()
==
ClientAuth
.
NEED
)
{
factory
.
setNeedClientAuth
(
true
);
factory
.
setWantClientAuth
(
true
);
}
else
if
(
ssl
.
getClientAuth
()
==
ClientAuth
.
WANT
)
{
factory
.
setWantClientAuth
(
true
);
}
}
private
void
configureSslPasswords
(
SslContextFactory
factory
,
Ssl
ssl
)
{
if
(
ssl
.
getKeyStorePassword
()
!=
null
)
{
factory
.
setKeyStorePassword
(
ssl
.
getKeyStorePassword
());
}
if
(
ssl
.
getKeyPassword
()
!=
null
)
{
factory
.
setKeyManagerPassword
(
ssl
.
getKeyPassword
());
}
}
private
void
configureSslKeyStore
(
SslContextFactory
factory
,
Ssl
ssl
)
{
try
{
URL
url
=
ResourceUtils
.
getURL
(
ssl
.
getKeyStore
());
factory
.
setKeyStoreResource
(
Resource
.
newResource
(
url
));
}
catch
(
IOException
ex
)
{
throw
new
EmbeddedServletContainerException
(
"Could not find key store '"
+
ssl
.
getKeyStore
()
+
"'"
,
ex
);
}
if
(
ssl
.
getKeyStoreType
()
!=
null
)
{
factory
.
setKeyStoreType
(
ssl
.
getKeyStoreType
());
}
if
(
ssl
.
getKeyStoreProvider
()
!=
null
)
{
factory
.
setKeyStoreProvider
(
ssl
.
getKeyStoreProvider
());
}
}
private
void
configureSslTrustStore
(
SslContextFactory
factory
,
Ssl
ssl
)
{
if
(
ssl
.
getTrustStorePassword
()
!=
null
)
{
factory
.
setTrustStorePassword
(
ssl
.
getTrustStorePassword
());
}
if
(
ssl
.
getTrustStore
()
!=
null
)
{
try
{
URL
url
=
ResourceUtils
.
getURL
(
ssl
.
getTrustStore
());
factory
.
setTrustStoreResource
(
Resource
.
newResource
(
url
));
}
catch
(
IOException
ex
)
{
throw
new
EmbeddedServletContainerException
(
"Could not find trust store '"
+
ssl
.
getTrustStore
()
+
"'"
,
ex
);
}
}
if
(
ssl
.
getTrustStoreType
()
!=
null
)
{
factory
.
setTrustStoreType
(
ssl
.
getTrustStoreType
());
}
if
(
ssl
.
getTrustStoreProvider
()
!=
null
)
{
factory
.
setTrustStoreProvider
(
ssl
.
getTrustStoreProvider
());
}
}
/**
* Configure the given Jetty {@link WebAppContext} for use.
* @param context the context to configure
...
...
spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java
View file @
62a5ce52
...
...
@@ -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
;
...
...
@@ -42,6 +43,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
;
...
...
@@ -50,12 +52,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
...
...
@@ -231,11 +237,87 @@ 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
)
{
Assert
.
state
(
connector
.
getProtocolHandler
()
instanceof
AbstractHttp11JsseProtocol
,
"To use SSL, the connector's protocol handler must be an "
+
"AbstractHttp11JsseProtocol subclass"
);
configureSsl
((
AbstractHttp11JsseProtocol
<?>)
connector
.
getProtocolHandler
(),
getSsl
());
connector
.
setScheme
(
"https"
);
connector
.
setSecure
(
true
);
}
for
(
TomcatConnectorCustomizer
customizer
:
this
.
tomcatConnectorCustomizers
)
{
customizer
.
customize
(
connector
);
}
}
/**
* Configure Tomcat's {@link AbstractHttp11JsseProtocol} for SSL.
* @param protocol the protocol
* @param ssl the ssl details
*/
protected
void
configureSsl
(
AbstractHttp11JsseProtocol
<?>
protocol
,
Ssl
ssl
)
{
protocol
.
setSSLEnabled
(
true
);
protocol
.
setSslProtocol
(
ssl
.
getProtocol
());
configureSslClientAuth
(
protocol
,
ssl
);
protocol
.
setKeystorePass
(
ssl
.
getKeyStorePassword
());
protocol
.
setKeyPass
(
ssl
.
getKeyPassword
());
protocol
.
setKeyAlias
(
ssl
.
getKeyAlias
());
configureSslKeyStore
(
protocol
,
ssl
);
String
ciphers
=
StringUtils
.
arrayToCommaDelimitedString
(
ssl
.
getCiphers
());
protocol
.
setCiphers
(
ciphers
);
configureSslTrustStore
(
protocol
,
ssl
);
}
private
void
configureSslClientAuth
(
AbstractHttp11JsseProtocol
<?>
protocol
,
Ssl
ssl
)
{
if
(
ssl
.
getClientAuth
()
==
ClientAuth
.
NEED
)
{
protocol
.
setClientAuth
(
Boolean
.
TRUE
.
toString
());
}
else
if
(
ssl
.
getClientAuth
()
==
ClientAuth
.
WANT
)
{
protocol
.
setClientAuth
(
"want"
);
}
}
private
void
configureSslKeyStore
(
AbstractHttp11JsseProtocol
<?>
protocol
,
Ssl
ssl
)
{
try
{
File
file
=
ResourceUtils
.
getFile
(
ssl
.
getKeyStore
());
protocol
.
setKeystoreFile
(
file
.
getAbsolutePath
());
}
catch
(
FileNotFoundException
ex
)
{
throw
new
EmbeddedServletContainerException
(
"Could not find key store "
+
ssl
.
getKeyStore
(),
ex
);
}
if
(
ssl
.
getKeyStoreType
()
!=
null
)
{
protocol
.
setKeystoreType
(
ssl
.
getKeyStoreType
());
}
if
(
ssl
.
getKeyStoreProvider
()
!=
null
)
{
protocol
.
setKeystoreProvider
(
ssl
.
getKeyStoreProvider
());
}
}
private
void
configureSslTrustStore
(
AbstractHttp11JsseProtocol
<?>
protocol
,
Ssl
ssl
)
{
if
(
ssl
.
getTrustStore
()
!=
null
)
{
try
{
File
file
=
ResourceUtils
.
getFile
(
ssl
.
getTrustStore
());
protocol
.
setTruststoreFile
(
file
.
getAbsolutePath
());
}
catch
(
FileNotFoundException
ex
)
{
throw
new
EmbeddedServletContainerException
(
"Could not find trust store "
+
ssl
.
getTrustStore
(),
ex
);
}
}
protocol
.
setTruststorePass
(
ssl
.
getTrustStorePassword
());
if
(
ssl
.
getTrustStoreType
()
!=
null
)
{
protocol
.
setTruststoreType
(
ssl
.
getTrustStoreType
());
}
if
(
ssl
.
getTrustStoreProvider
()
!=
null
)
{
protocol
.
setTruststoreProvider
(
ssl
.
getTrustStoreProvider
());
}
}
/**
* Configure the Tomcat {@link Context}.
* @param context the Tomcat context
...
...
spring-boot/src/test/java/org/springframework/boot/context/embedded/AbstractEmbeddedServletContainerFactoryTests.java
View file @
62a5ce52
This diff is collapsed.
Click to expand it.
spring-boot/src/test/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactoryTests.java
View file @
62a5ce52
...
...
@@ -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,27 @@ 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
();
this
.
container
.
start
();
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
;
...
...
spring-boot/src/test/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactoryTests.java
View file @
62a5ce52
...
...
@@ -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
;
...
...
@@ -228,6 +230,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
];
...
...
spring-boot/src/test/resources/test.jks
0 → 100644
View file @
62a5ce52
File added
spring-boot/src/test/resources/test.p12
0 → 100644
View file @
62a5ce52
File added
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment