Spring Boot possède certaines propriétés pour configurer le port Web et les paramètres SSL, mais une fois qu'un certificat SSL est défini, le port http se transforme en port https.
Alors, comment puis-je faire fonctionner les deux ports, par exemple: 80 et 443 en même temps?
Comme vous pouvez le voir, il n'y a que des propriétés pour un port, dans ce cas "server.ssl" est activé, ce qui rend le port http désactivé automatiquement.
##############
### Server ###
##############
server.port=9043
server.session-timeout=1800
server.ssl.key-store=file:///C:/Temp/config/localhost.jks
server.ssl.key-store-password=localhost
server.ssl.key-password=localhost
server.ssl.trust-store=file:///C:/Temp/config/localhost.jks
server.ssl.trust-store-password=localhost
J'essaie d'utiliser même Tomcat ou Undertow. J'apprécierais toute aide!
La configuration Spring Boot à l'aide des propriétés permet de configurer un seul connecteur. Vous avez besoin de plusieurs connecteurs et pour cela, vous devez écrire une classe de configuration. Suivez les instructions dans
Vous pouvez trouver un exemple de configuration de https via les propriétés, puis http via EmbeddedServletContainerCustomizer ci-dessous
server:
port:
8080
ssl:
enabled:
true
keyStoreType:
PKCS12
key-store:
/path/to/keystore.p12
key-store-password:
password
http:
port:
8079
@Configuration
public class TomcatConfig {
@Value("${server.http.port}")
private int httpPort;
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
TomcatEmbeddedServletContainerFactory containerFactory =
(TomcatEmbeddedServletContainerFactory) container;
Connector connector = new Connector(TomcatEmbeddedServletContainerFactory.DEFAULT_PROTOCOL);
connector.setPort(httpPort);
containerFactory.addAdditionalTomcatConnectors(connector);
}
}
};
}
}
La réponse actuellement acceptée fonctionne parfaitement mais nécessite une certaine adaptation si vous souhaitez qu'elle fonctionne avec Spring Boot 2.0.0 et versions ultérieures:
@Component
public class HttpServer {
@Bean
public ServletWebServerFactory servletContainer(@Value("${server.http.port}") int httpPort) {
Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setPort(httpPort);
TomcatServletWebServerFactory Tomcat = new TomcatServletWebServerFactory();
Tomcat.addAdditionalTomcatConnectors(connector);
return Tomcat;
}
}
ou la version kotlin:
@Component
class HttpServer {
@Bean
fun servletContainer(@Value("\${server.http.port}") httpPort: Int): ServletWebServerFactory {
val connector = Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL)
connector.setPort(httpPort)
val Tomcat = TomcatServletWebServerFactory()
Tomcat.addAdditionalTomcatConnectors(connector)
return Tomcat
}
}
Spring Boot ne permet d'ouvrir qu'un port par configuration. Le deuxième port doit être ouvert par programme.
import org.springframework.boot.web.embedded.undertow.UndertowServletWebServerFactory;
import org.springframework.boot.web.server.WebServerFactoryCustomizer;
@Configuration
public class UndertowConfig {
@Value("${server.http.port}")
private int httpPort;
@Value("${server.http.interface}")
private String httpInterface;
@Bean
public WebServerFactoryCustomizer<UndertowServletWebServerFactory> containerCustomizer() {
return (WebServerFactoryCustomizer) factory -> {
UndertowServletWebServerFactory undertowFactory = (UndertowServletWebServerFactory) factory;
undertowFactory.getBuilderCustomizers().add(builder -> {
builder.addHttpListener(httpPort, httpInterface);
});
};
}
}
Spring peut ouvrir une propriété de lecture de port HTTP ou HTTPS à partir d'une source de propriété disponible. Si vous ajoutez la configuration appropriée comme indiqué ci-dessous, il serait suffisant d'avoir le port HTTP ouvert.
#default secured port (Spring will open it automatically)
server.port=8443
#additional HTTP port (will open it in UndertowConfig)
server.http.port=8080
#Open to the world
server.http.interface=0.0.0.0
#These settings tell Spring to open SSL port
server.ssl.keystore=file:${APP_BASE}/conf/server/ssl_selfsigned/server.keystore
server.ssl.key-store-password=xyz
server.ssl.key-password=xyz
Vous pouvez ouvrir un autre port SSL de la même manière que vous avez ouvert le port HTTP si vous le souhaitez en procédant ainsi
.addHttpsListener(ssl_port, httpInterface, getSSLContext());
Voici comment créer un contexte SSL
import javax.net.ssl.*;
import Java.io.InputStream;
import Java.nio.file.Files;
import Java.nio.file.Paths;
import Java.security.KeyStore;
public SSLContext getSSLContext() throws Exception
{
return createSSLContext(loadKeyStore(serverKeystore,keyStorePassword),
loadKeyStore(serverTruststore,trustStorePassword));
}
private SSLContext createSSLContext(final KeyStore keyStore,
final KeyStore trustStore) throws Exception {
KeyManager[] keyManagers;
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(keyStore, keyStorePassword.toCharArray());
keyManagers = keyManagerFactory.getKeyManagers();
TrustManager[] trustManagers;
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(trustStore);
trustManagers = trustManagerFactory.getTrustManagers();
SSLContext sslContext;
sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagers, trustManagers, null);
return sslContext;
}
private static KeyStore loadKeyStore(final String storeLoc, final String storePw) throws Exception {
InputStream stream = Files.newInputStream(Paths.get(storeLoc));
if(stream == null) {
throw new IllegalArgumentException("Could not load keystore");
}
try(InputStream is = stream) {
KeyStore loadedKeystore = KeyStore.getInstance("JKS");
loadedKeystore.load(is, storePw.toCharArray());
return loadedKeystore;
}
}
Une autre solution Spring boot 2.x:
private static final int HTTP_PORT = 80;
private static final int HTTPS_PORT = 443;
private static final String HTTP = "http";
private static final String USER_CONSTRAINT = "CONFIDENTIAL";
@Bean
public ServletWebServerFactory servletContainer() {
TomcatServletWebServerFactory Tomcat = new TomcatServletWebServerFactory() {
@Override
protected void postProcessContext(Context context) {
SecurityConstraint securityConstraint = new SecurityConstraint();
securityConstraint.setUserConstraint(USER_CONSTRAINT);
SecurityCollection collection = new SecurityCollection();
collection.addPattern("/*");
securityConstraint.addCollection(collection);
context.addConstraint(securityConstraint);
}
};
Tomcat.addAdditionalTomcatConnectors(redirectConnector());
return Tomcat;
}
private Connector redirectConnector() {
Connector connector = new Connector(
TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
connector.setScheme(HTTP);
connector.setPort(HTTP_PORT);
connector.setSecure(false);
connector.setRedirectPort(HTTPS_PORT);
return connector;
}
Et définissez vos propriétés server.port = 44
Jetez un œil à: https://github.com/creactiviti/spring-boot-starter-acme . Il est très facile de générer automatiquement un certificat SSL basé sur LetsEncrypt.
Du README:
Ajoutez le module à votre fichier pom.xml en tant que dépendance.
Construisez votre projet.
Déployez-le sur une machine cible et pointez votre nom de domaine vers l'adresse IP de cette machine. LetsEncrypt valide votre propriété du domaine en effectuant un rappel au point de terminaison http: //your-domain/.well-known/acme-challenge/ {token} exposé par ce module.
Assurez-vous que votre serveur a openssl disponible sur son $ PATH.
Pour activer spring-boot-starter-acme et générer un certificat, exécutez:
Sudo Java -Dserver.port=80 -Dacme.enabled=true -Dacme.domain-name=<YOUR_DOMAIN_NAME> -Dacme.accept-terms-of-service=true -jar mysecureapp-0.0.1-SNAPSHOT.jar
Vérifiez sur votre console que le certificat a bien été généré.
Arrêtez votre application et configurez-la pour utiliser le certificat généré:
server.port=443 server.ssl.key-store=keystore.p12 server.ssl.key-store-password=password server.ssl.keyStoreType=PKCS12