Generating SSL Certificates
Before configuring the server, you need to generate a valid SSL certificate. The Java keytool utility provides two common approaches for creating keystores. Choose the method that best fits your security requirements.
The first option uses RSA encryption with a PKCS12 format keystore, which offers broad compatibility:
keytool -genkey -alias myhttps -keyalg RSA -keysize 2048 -keystore /path/to/keystore.p12 -validity 365
The alternative approach generates an elliptic curve certificate with a JKS keystore:
keytool -genkeypair -alias myhttps -keyalg EC -keysize 256 -validity 365 -keypass your_password -keystore /path/to/keystore.jks -storepass your_password -storetype jks
Important: The alias name must match the configuration value you set in your application properties. In these examples, the alias is myhttps, which corresponds to the keystore configuration in your YAML file.
Project Configuration
After generating the keystore, place the certificate file in you're project's src/main/resources directory. Then configure your application properties file with the appropriate SSL settings:
server:
port: 8443
ssl:
key-store: classpath:keystore.p12
key-store-type: PKCS12
key-store-password: your_password
key-alias: myhttps
You can maintain separate configurations for different environments by using profile-specific files such as application-dev.yml or application-prod.yml.
Configuring HTTP to HTTPS Redirect
Most production deployments require that all HTTP traffic be automatically redirected to HTTPS. This ensures secure communication even when users initially request an unsecured connection. Create a configuration class to handle this redirection:
import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.tomcat.util.descriptor.web.SecurityCollection;
import org.apache.tomcat.util.descriptor.web.SecurityConstraint;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class HttpsRedirectConfig {
@Value("${server.port}")
private int securePort;
private Connector createHttpConnector() {
Connector httpConnector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
httpConnector.setScheme("http");
httpConnector.setSecure(false);
httpConnector.setPort(8080);
httpConnector.setRedirectPort(securePort);
return httpConnector;
}
@Bean
public TomcatServletWebServerFactory tomcatContainerFactory() {
TomcatServletWebServerFactory factory = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint("CONFIDENTIAL");
SecurityCollection securityCollection = new SecurityCollection();
securityCollection.addPattern("/*");
securityConstraint.addCollection(securityCollection);
context.addConstraint(securityConstraint);
}
};
factory.addAdditionalTomcatConnectors(createHttpConnector());
return factory;
}
}
This configuration accomplishes two objectives: it creates an HTTP connector listening on port 8080, and it configures the security constraint that forces all traffic through the secure port. When a user accesses port 8080, Tomcat automatically redirects them to the HTTPS port.
Troubleshooting Keystore Format Errors
Despite correct configuration, you may encounter an "Invalid keystore format" error during application startup. This typically indicates a mismatch between the keystore type specified in your configuration and the actual file format.
Resolve this issue by ensuring your pom.xml correctly handles the keystore file during the build process. Add the following plugin configuration to ensure proper resource handling:
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<includes>
<include>**/*.jks</include>
<include>**/*.p12</include>
<include>**/*.pem</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>
The filtering setting set to false prevents Spring Boot from attempting to process binary files as text resources, which would corrupt the keystore contents.
With these configurations in place, your Spring Boot application serves HTTPS traffic securely, and all HTTP requests automatically redirect to the secure endpoint.