Secure Sockets Layer (SSL) is a security protocol in which data is encrypted and sent to a trusted party via a certificate. In this part, I will show you the different ways to create a secured connection with Spring Boot. The completion of these steps is not mandatory to start the next chapter. They are included for completeness, so feel free to skip them if you are in a hurry to deploy your application to the cloud.
In Chapter 8, Deploying Your Web Application to the Cloud, we will see that most cloud platforms already handle SSL so we don't have to configure it at our end.
Normally, X.509 certificates are delivered by a Certificate Authority. They generally bill you for the service, so for testing purposes, we can create our own self-signed keystore file.
The JDK comes with a binary called keytool, which is used to manage certificates. With it, you can create a keystore and import certificates into an existing keystore. You can issue the following command inside your project root to create one:
$ keytool -genkey -alias masterspringmvc -keyalg RSA -keystore src/main/resources/tomcat.keystore Enter keystore password: password Re-enter new password: password What is your first and last name? [Unknown]: Master Spring MVC What is the name of your organizational unit? [Unknown]: Packt What is the name of your organization? [Unknown]: Packt What is the name of your City or Locality? [Unknown]: Paris What is the name of your State or Province? [Unknown]: France What is the two-letter country code for this unit? [Unknown]: FR Is CN=Master Spring MVC, OU=Packt, O=Packt, L=Paris, ST=France, C=FR correct? [no]: yes Enter key password for <masterspringmvc> (RETURN if same as keystore password): password2 Re-enter new password: password2
This will generate a keystore named masterspringmvc
with the RSA algorithm and will store it in a keystore in src/main/resources
.
If all you care about is having one secure https channel and no http channel, it is as easy as it gets:
server.port = 8443 server.ssl.key-store = classpath:tomcat.keystore server.ssl.key-store-password = password server.ssl.key-password = password2
If you want to have both the http and the https channels available in your application, you should add this kind of configuration to your application:
@Configuration public class SslConfig { @Bean public EmbeddedServletContainerFactory servletContainer() throws IOException { TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory(); tomcat.addAdditionalTomcatConnectors(createSslConnector()); return tomcat; } private Connector createSslConnector() throws IOException { Connector connector = new Connector(Http11NioProtocol.class.getName()); Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler(); connector.setPort(8443); connector.setSecure(true); connector.setScheme("https"); protocol.setSSLEnabled(true); protocol.setKeyAlias("masterspringmvc"); protocol.setKeystorePass("password"); protocol.setKeyPass("password2"); protocol.setKeystoreFile(new ClassPathResource("tomcat.keystore").getFile().getAbsolutePath()); protocol.setSslProtocol("TLS"); return connector; } }
This will load the previously generated keystore to create an additional channel on port 8443 in addition to port 8080.
You can use Spring Security to automatically redirect connections from http
to https
with the following configuration:
@Configuration public class WebSecurityConfiguration extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http .requiresChannel().anyRequest().requiresSecure() .and() /* rest of the configuration */; } }
The most convenient way to secure your application with SSL is often to put it behind an SSL-enabled web server such as Apache or CloudFlare. These will often use de facto headers to indicate that the connection was previously initiated with SSL.
Spring Boot can understand this protocol if you tell it what the correct headers are in your application.properties
file:
server.tomcat.remote_ip_header=x-forwarded-for server.tomcat.protocol_header=x-forwarded-proto
See the documentation here for more details at http://docs.spring.io/spring-boot/docs/current/reference/html/howto-embedded-servlet-containers.html#howto-use-tomcat-behind-a-proxy-server.