Как сконфигурировать Spring web client под SSL

Допустим, у нас есть приложение на Spring, оно отправляет rest-запросы в другой сервис по https. Нужно настроить подключение нашего клиента — spring web client к серверу с использованием ssl.

Не нашел явно подходящего мне решения в интернете, поэтому хочу поделиться, как это получилось у меня. В решении мне помогли stackoverflow и пример конфигурирования SSL (ссылки в конце).

Начинаем

Конфигурация

У нас есть файл со свойствами — application.properties или application.yml. В нем мы укажем путь к файлу с сертификатами пользователя и ключами, путь к файлу с доверенными сертификатами (обычно это один файл) и пароли.

ssl:   trust-store-location: classpath:key.jks   trust-store-password: password   trust-store-type: jks   key-store-location: classpath:key.jks   key-store-password: password   key-store-type: jks   key-password: password

Создадим класс, который будет соответствовать этой конфигурации.

@Configuration @ConfigurationProperties("ssl") @Data public class SslProperties {     Resource trustStoreLocation;     String trustStorePassword;     String trustStoreType;      Resource keyStoreLocation;     String keyStorePassword;     String keyStoreType;     String keyPassword; }

Создадим бин, который будет выполнять “пред-настройку” нашего клиента:

@Configuration @AllArgsConstructor public class HttpConfig {     private SslProperties props;          @Bean     public WebClientCustomizer configureWebclient() {          return (WebClient.Builder builder) -> {              try {                 SslContext sslContext = createSslContext();                  HttpClient httpClient = HttpClient.create()                     .secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));                  ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);                 builder.clientConnector(connector);              } catch (KeyStoreException | CertificateException | NoSuchAlgorithmException | IOException | UnrecoverableKeyException e) {                 throw new RuntimeException(e);             }         };      }      private SslContext createSslContext() throws IOException, KeyStoreException, CertificateException, NoSuchAlgorithmException, UnrecoverableKeyException {         // инициализируем keyManagerFactory для keyStore  KeyStore keyStore = KeyStore.getInstance(props.getKeyStoreType());         keyStore.load(props.getKeyStoreLocation().getInputStream(), props.getKeyStorePassword().toCharArray());         KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());         keyManagerFactory.init(keyStore, props.getKeyPassword().toCharArray());  // инициализируем keyManagerFactory для trustStore          KeyStore trustStore = KeyStore.getInstance(props.getTrustStoreType());         trustStore.load(props.getTrustStoreLocation().getInputStream(), props.getTrustStorePassword().toCharArray());         TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());         trustManagerFactory.init(trustStore);          return SslContextBuilder.forClient()             .trustManager(trustManagerFactory)             .keyManager(keyManagerFactory)             .build();     }  }

Использование

Далее подключим этот бин в клиенте:

@Service @RequiredArgsConstructor public class Client {      private final WebClient.Builder builder;      public void sendRq() {         builder.build()             .post()   // далее логика по отправке запроса и обработке ответа     } }

Тестирование

Тестировал эту штуку с mockito. Сконфигурировал примерно так:

public class ClientTest {      private Client client; private WebClient.Builder builder;     private WebClient webClientMock;      @BeforeEach     public void setUp() {         webClientMock = mock(WebClient.class);  builder = mock(WebClient.Builder.class);         client = spy(new Client(builder));     }      @Test     public void testFeatureShouldWork() {        when(builder.build()).thenReturn(webClientMock); }  }

Заключение

Кажется, что получилась довольно гибкая и удобная конфигурация. Если у вас есть опыт или интересные ссылки для конфигурирования SSL в spring web client, поделитесь, пожалуйста, в комментариях.

Ссылки, которые помогли мне собрать такой вариант:


ссылка на оригинал статьи https://habr.com/ru/articles/737906/

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *