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:
- Obtener certificado SSL
- Habilitar HTTPS en Spring Boot
- 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:
- Server SSL: https://github.com/rcrespop/server-ssl
- Client SSL: https://github.com/rcrespop/client-ssl
Referencias
- Using a custom trust store with RestTemplate in Spring Boot
- How to call a REST API protected with SSL (https) from Spring Boot without importing the certificate into java keystore.
- How to enable HTTPS in a Spring Boot Java Application
- Spring Boot Docs – Configure SSL
Si te gustó el artículo, suscríbete a mi newsletter
One response
Como seria lo mismo pero para levantar un servicio Soap?