javaspringspring-bootsslspring-resttemplate

Spring Boot 3.4 new feature : How to config SSLBundle works with RestClient?


I am using Spring Boot 3.4.1 , JDK 23, MySQL 9. I am excited with new feature RestClient inside new Spring Framework version . I can done mutualTLS with RestTemplate without any concern, now I want experience very new feature RestClient in context of SSLBundle (or if cannot, use SSLContext).

File application.yml

server:
  port: 8001
  ssl:
      bundle: bar
      client-auth: NEED
      enabled: true
spring:
    datasource:
        driver-class-name: com.mysql.cj.jdbc.Driver
        url: jdbc:mysql://localhost:3306/fuu001?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true
        username: ggAABB
        password: XXxxYY
    ssl:
        bundle:
            jks:
                foo:
                    keystore:
                        location: C:\\ssl\\server-identity.p12
                        password: fdfd
                        type: PKCS12
                    truststore:
                        location: C:\\ssl\\server-truststore.p12
                        password: dfsdfsd
                        type: PKCS12
                    reload-on-update: true
                bar:
                    keystore:
                        location: C:\\ssl\\client-identity.p12
                        password: dfdsfs
                        type: PKCS12
                    truststore:
                        location: C:\\ssl\\client-truststore.p12
                        password: fdsfd
                        type: PKCS12
                    reload-on-update: true
    jpa:
        hibernate:
          ddl-auto: create-drop
        properties:
          hibernate:
              format_sql: true
        show-sql: true
#    security:
#      user:
#          name: user
#          password: user

File CallFooService.java has content

package com.example;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestClient;
import org.springframework.web.client.RestTemplate;

import java.util.Map;

@Service
public class CallFooService {

    @Autowired
    private RestTemplate restTemplate;

    public void testMethod(){
        String response = restTemplate.getForObject("https://localhost:8001/user", String.class);
        System.out.println("response = " + response);

        String response2 = restTemplate.getForObject("https://localhost:8002/user", String.class);
        System.out.println("response2 = " + response2);


        RestClient defaultClient = RestClient.create();

        RestClient customClient = RestClient.builder()
                .requestFactory(new HttpComponentsClientHttpRequestFactory()) // I want inject SSLBundle or SSL Context at here or something else.
                .messageConverters(converters -> converters.add(null))
                .baseUrl("https://example.com")
                .defaultUriVariables(Map.of("variable", "foo"))
                .defaultHeader("My-Header", "Foo")
                .defaultCookie("My-Cookie", "Bar")
                .requestInterceptor(null)
                .requestInitializer(null)
                  // I want inject SSLBundle or SSL Context at here or something else.
                .build();
    }

}

Spring Boot 3.4.1 : How to config SSLBundle works with RestClient?

Related:


Solution

  • Base on RestTemplate

    package com.example;
    
    import org.springframework.boot.ssl.SslBundles;
    import org.springframework.boot.web.client.RestTemplateBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.client.RestTemplate;
    
    @Configuration
    public class RestTemplateConfig {
    
        @Bean(name = "foobarbazz")
        public RestTemplate restTemplate(RestTemplateBuilder builder, SslBundles sslBundles) {
            return builder.sslBundle(sslBundles.getBundle("foo")).build();
        }
    
    }
    

    then

    import org.springframework.web.client.RestClient;
    import org.springframework.web.client.RestTemplate;
    
    //...
    
    RestClient defaultClient = RestClient.create(restTemplate);
    
    String result = defaultClient.get().uri("https://localhost:8002/user").retrieve().body(String.class);
    System.out.println("restclient call >>> " + result);
    

    Solution: We can use SSLBundle inside RestClient via RestTemplate indirectly. Almost/Maybe this way is not best way. I also wait for other ways.

    Reference: https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/client/RestClient.html#builder(org.springframework.web.client.RestTemplate)