carlosalberto
Spring Boot tiene algunas propiedades para configurar el puerto web y la configuración de SSL, pero una vez que se establece un certificado SSL, el puerto http se convierte en un puerto https.
Entonces, ¿cómo puedo mantener ambos puertos funcionando, por ejemplo: 80 y 443 al mismo tiempo?
Como puede ver, solo hay propiedades para un puerto, en este caso “server.ssl” está habilitado, lo que hace que el puerto http se deshabilite automáticamente.
##############
### 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
Estoy tratando de usar incluso Tomcat o Undertow. ¡Agradecería cualquier ayuda!
Harish Gokavarapu
La configuración de Spring Boot usando propiedades, permite configurar solo un conector. Lo que necesita son múltiples conectores y para esto, debe escribir una clase de Configuración. Siga las instrucciones en
Puede encontrar un ejemplo práctico de configuración de HTTPS a través de propiedades y luego HTTP a través de EmbeddedServletContainerCustomizer a continuación
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);
}
}
};
}
}
-
y
server.http.port
ya no parece existir.– Stefan Falk
28 de diciembre de 2018 a las 23:57
-
El puerto http del servidor @displayname es una configuración personalizada definida por el programador y no predefinida en Spring, en el código se puede ver: @Value(“${server.http.port}”) private int httpPort;
– usuario666
18 de enero de 2019 a las 12:40
-
@ user666 Solía existir afaik.
– Stefan Falk
18 de enero de 2019 a las 12:41
-
@Harish Gokavarapu y Adam Millerchip, ¿cómo hacen esto en la línea de comando? Con una configuración de springboot https, probé esta: -Dserver.port=6010 -Dserver.http.port=6011, pero solo se cambió el puerto https, no el puerto http.
– Artanis Zeratul
16 de agosto de 2019 a las 1:59
-
Esto funcionó para mí, excepto que tuve que cambiar los valores del puerto. http.port debe ser su 8080 básico y server.port debe ser su puerto https deseado, como 8443
– A Forsberg
3 de enero de 2020 a las 15:15
NickDK
La respuesta aceptada actualmente funciona perfectamente, pero necesita alguna adaptación si desea que funcione con Spring Boot 2.0.0
y en adelante:
@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;
}
}
o el versión 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
}
}
-
Funcionó perfectamente en la versión más nueva de Spring Boot.
– usuario666
18 de enero de 2019 a las 13:28
-
Esto funcionó para mí también. Solo quería aclarar que esta clase REEMPLAZA la clase TomcatConfig en la respuesta aceptada. También se aplica mi comentario sobre la respuesta aceptada sobre ajustar las propiedades de yaml.
– A Forsberg
7 febrero 2020 a las 17:41
-
Funciona bien para soporte HTTP/HTTPS probado con Spring Boot
2.4.3
versión.– catch23
20 de marzo de 2021 a las 19:23
-
¿Cuál es la importación para la clase Connector?
– Anurag Bhalekar
11 oct 2021 a las 14:51
Stan Sokolov
A continuación se muestra un ejemplo simple de cómo habilitar ambos puertos HTTP/HTTPS para resaca.
Spring Boot solo permite abrir un puerto por configuración. El segundo puerto debe abrirse mediante programación.
Abra el puerto HTTP primero mediante programación.
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);
});
};
}
}
HTTPS por configuración
Spring puede abrir una propiedad de lectura de puerto HTTP o HTTPS desde una fuente de propiedad disponible. Si agrega la configuración adecuada como se muestra a continuación, sería lo suficientemente bueno para tener abierto el puerto HTTP.
#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
HTTPS por configuración manual
Puede abrir otro puerto SSL de la misma manera que abrió el puerto HTTP si lo desea haciendo esto
.addHttpsListener(ssl_port, httpInterface, getSSLContext());
Así es como puedes crear un contexto 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;
}
}
-
Esta solución funciona perfectamente con resaca, gracias.
– norbertas.gaulia
20 de enero de 2019 a las 20:49
-
¿Puede agregar algunos códigos en la implementación anterior para HTTP 2.0?
– Sam
13 de febrero de 2019 a las 15:27
-
en mi caso el
@Value
la inyección no funcionó tan fácilmente porque mi configuración era más compleja. Le expliqué mi situación y lo que terminó funcionando para mí en este comentario de problema de GitHub.– Alejandro González
15 de diciembre de 2021 a las 10:02
Otra solución 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;
}
Y establecer en sus propiedades servidor.puerto=443
Echa un vistazo a: https://github.com/creactiviti/spring-boot-starter-acme. Hace que sea muy fácil generar automáticamente un certificado SSL basado en LetsEncrypt.
Del LÉAME:
-
Agregue el módulo a su archivo pom.xml como una dependencia.
-
Construye tu proyecto.
-
Despliéguelo en una máquina de destino y apunte su nombre de dominio a la dirección IP de esa máquina. LetsEncrypt valida su propiedad del dominio haciendo una devolución de llamada al http://tu-dominio/.bien-conocido/acme-challenge/Punto final {token} expuesto por este módulo.
-
Asegúrese de que su servidor tenga Openssl disponible en su $PATH.
-
Para activar spring-boot-starter-acme y generar un certificado ejecute:
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
-
Verifique su consola para obtener una confirmación de que el certificado se generó con éxito.
-
Detenga su aplicación y configúrela para hacer uso del certificado generado:
server.port=443
server.ssl.key-store=keystore.p12
server.ssl.key-store-password=password
server.ssl.keyStoreType=PKCS12
Shai Almog
Las respuestas principales son excelentes y probablemente funcionen, pero he estado usando Undertow con JHipster, por lo que no me funcionaron (y esta fue la principal búsqueda resultado). El código correcto para Undertow se menciona en este problema específicamente:
@Bean
public UndertowServletWebServerFactory embeddedServletContainerFactory() {
UndertowServletWebServerFactory factory = new UndertowServletWebServerFactory();
factory.addBuilderCustomizers(new UndertowBuilderCustomizer() {
@Override
public void customize(Undertow.Builder builder) {
builder.addHttpListener(8080, "0.0.0.0");
}
});
return factory;
}
¿Por qué quieres que ambos funcionen al mismo tiempo? O la línea es segura o insegura, pero no debería ser ambas cosas.
– Makoto
17 de junio de 2015 a las 15:42
Algunas partes de mi proyecto necesitan ser aseguradas y otras no. Como saben, el tráfico Https es más lento que Http, por lo que me gustaría intercambiar ambos protocolos al mismo tiempo que lo hacemos en cualquier servidor de aplicaciones.
– Carlos Alberto
17 de junio de 2015 a las 15:44
@Makoto – no necesariamente. un puerto puede admitir tanto HTTP como HTTPS. por ejemplo – bayou.io/release/0.9/docs/http/Server_SSL_Configuration.html
– Zhong Yu
17 de junio de 2015 a las 15:48
@ElLordCode: no estoy familiarizado con Boot; Entonces, ¿está diciendo que solo puede tener un puerto?
– Zhong Yu
17/06/2015 a las 15:50
posible duplicado de la ejecución de una aplicación Spring Boot (Tomcat integrado) con SSL y sin cifrar simultáneamente
–Andy Wilkinson
17 de junio de 2015 a las 20:14