BLOG

Programación-Tecnología

Habilitar HTTPS en Spring Boot requiere primero obtener un certificado SSL y luego configurarlo. Te mostraré los pasos a seguir para proteger un API REST en Spring Boot para ser consumida por HTTPS.

A continuación los pasos a realizar:

  1. Obtener certificado SSL
  2. Habilitar HTTPS en Spring Boot
  3. Llamar a un API REST por HTTPS desde Spring Boot.

PASO 1: Obtener certificado SSL

A la hora de generar un certificado SSL, podemos bien hacerlo nosotros mismos (autofirmado) o bien utilizar uno emitido por una entidad certificadora de confianza (CA). Los certificados autofirmados son ideales para entornos de desarrollo y con propósitos de testing, mientras que en entornos productivos se deberían utilizar certificados emitidos por una CA.

En este caso vamos a generar un certificado autofirmado. Para ello, puedes utilizar cualquiera de las siguientes herramientas:

  • Keytool: utilidad incluida en el JDK para gestionar certificados. Para usarla, ejecuta el comando keytool –help en un terminal. Aquí te dejo la documentación oficial.
  • Keystore Explorer: se trata de una herramienta visual que nos facilita la gestión de certificados. Puedes descargarla aquí.

En mi caso utilizaré keystore explorer para crear un nuevo keystore donde guardar el certificado SSL que generemos:

1.- Crea un nuevo keystore de tipo PKCS#12:

2.- Una vez creado el keystore, vamos a generar un nuevo par de claves (recuerda que también puedes importar un certificado si ya dispones de uno):

3.- Clic en el icono “Name” y edita las propiedades del certificado:

4.- Clic en el botón Add Extensions. Necesitarás añadir tu dominio y dirección IP si están probando desde tu máquina local:

5.- Selecciona Subject Alernative Name:

6.- Añade localhost y tu IP local (127.0.0.1):

7.- Asigna un alias y una contraseña a la key:

8.- El par de claves del certificado SSL ha sido generada:

9.- Clic en el icono “Save” y asigna la contraseña de acceso al keyStore:

10.- Por último guarda el keystore con extensión .p12:

¡El keystore con el certificado SSL está listo para ser usado!

PASO 2: Habilitar HTTPS en Spring Boot

Una vez que creado el keystore con el certificado, el siguiente paso será configurar la aplicación Spring Boot para que acepte peticiones HTTPS.

Por simplicidad y para facilitar el testing, lo primero será ubicar el fichero del keystore en la carpeta resources del proyecto Spring Boot. En entornos productivos, lo recomendable sería utilizar una solución de gestión de secretos para manejar el keystore.

Para habilitar HTTPS en Spring Boot, abre el fichero application.yml del proyecto y define las siguientes propiedades:

server:
  ssl:
    key-store: classpath:mycert.p12
    key-store-password: mykspwd
    key-alias: mykey    
    key-password: mykeypwd
    key-store-type: pkcs12
  port: 8443

Por último, creamos un controller que nos permita exponer un API REST sencilla protegida con SSL:

@RestController
@RequestMapping("/server-ssl")
public class ServerSslController {

    @GetMapping("/test")
    public String testSSL()  {
        return "Hello from SSL server";
    }
}

Ejecuta la aplicación Spring Boot y, con tu browser, haz una llamada al API REST por HTTPS (https://localhost:8443/server-ssl/test). Seguramente obtengas el mensaje parecido a este:

Esto ocurre la primera vez que intentas acceder al servidor SSL y es debido a que al usar un certificado autofirmado en lugar de uno emitido por una CA de confianza, el browser no lo reconoce, por lo que nos pide autorización para continuar. Haz clic en el botón “Avanzado” y luego pincha en el enlace “continuar a localhost (no seguro)”. Ahora sí que deberías ver el mensaje devuelto por el API REST.

PASO 3: Llamar a un API REST por HTTPS desde Spring Boot

Para llamar al API REST de forma segura vamos a necesitar usar un certificado SSL. Para ello existen dos maneras de acceder a su ubicación y utilizarlo:

  • JVM trust store: importar el certificado en el keystore por defecto de java (.cacert), ubicado generalmente en el path java.home\lib\security.
  • Keystore: importar el certificado en un keystore generado por nosotros mismos.

En este caso, reutilizaremos el keystore creado en el paso 1, el cual tienes que ubicar en la carpeta resources del proyecto Spring Boot de nuestro cliente SSL:

Añade las siguientes propiedades en el fichero application.yml del proyecto:

client:
  ssl:
    key-store: classpath:mycert.p12
    key-store-password: mykspwd

Para realizar la llamada a un API REST de forma segura por HTTPS, no podemos usar un REST template por defecto. Es necesario crear un custom REST template, que nos permita cargar el keystore con el certificado SSL.  Para ello vamos a crear un nuevo bean REST template en una clase de configuración donde definiremos un contexto SSL para cargar nuestro certificado SSL.

@Configuration
public class ClientSslConfiguration {

    @Value("${client.ssl.key-store}")
    private Resource trustStore;
    @Value("${client.ssl.key-store-password}")
    private String trustStorePassword;

    String protocol = "TLSv1.2";

    @Bean
    RestTemplate restTemplate() throws Exception {

        SSLContext sslContext = new SSLContextBuilder()
                .loadTrustMaterial(
                        trustStore.getURL(),
                        trustStorePassword.toCharArray()
                ).build();

        SSLConnectionSocketFactory socketFactory =
                new SSLConnectionSocketFactory(sslContext);

        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory).build();

        HttpComponentsClientHttpRequestFactory factory =
                new HttpComponentsClientHttpRequestFactory(httpClient);

        return new RestTemplate(factory);
    }
}

Por último, sólo nos queda implementar la llamada al API REST del servidor SSL por HTTPS utilizando nuestro Custom REST Template.

@Service
public class ClientSslService {

    @Autowired
    RestTemplate restTemplate;

    public String testSSL() {

        String response;

        String fooResourceUrl = "https://localhost:8443/server-ssl";
        response = restTemplate.getForObject(fooResourceUrl + "/test", String.class);
            
        return response;
    }
}

Ya estamos listos para probar nuestro cliente SSL. Ejecuta la aplicación Spring Boot y comprueba que la llamada por HTTPS al API REST del servidor SSL se realiza correctamente:

Código fuente

A continuación, te dejos los enlaces al código del cliente y servidor SSL:

Referencias

Si te gustó el artículo, suscríbete a mi newsletter

Comparte este artículo si te gustó:

One response

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.