RestTemplate: ошибка отправки application/x-www-form-urlencoded

Есть у меня запрос на авторизацию, который нужно использовать для интеграции с другой системой.

Выглядит он так:

curl --location --request POST 'https://path/to/auth/service' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=DOMAIN\username' \
--data-urlencode 'password=password' \
--data-urlencode 'client_id=441345C435-23433454V5FC-34TVRVT5VT' \
--data-urlencode 'resource=https://path/to/resource'

Выполняю запрос в IDEA (если знаете, в IDEA есть http-клиент), получается что-то вроде:

POST https://path-to-auth-service
Content-Type: application/x-www-form-urlencoded

grant_type=password&username=DOMAIN\username&password=password&client_id=441345C435-23433454V5FC-34TVRVT5VT&resource=https%3A%2F%path%2to%2resource

Запрос отлично выполняется, возвращая мне токены. Дело доходит до написания запроса в приложении. Во-первых, требуется локально подписанный сертификат, нашёл такой рецепт где-то на стэке:

@Configuration
public class RestTemplateConfig {

    @Bean
    public RestTemplate restTemplate() throws KeyStoreException, NoSuchAlgorithmException, KeyManagementException {
        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;

        SSLContext sslContext = SSLContexts.custom()
                .loadTrustMaterial(null, acceptingTrustStrategy)
                .build();

        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(sslContext);

        CloseableHttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(csf)
                .build();

        HttpComponentsClientHttpRequestFactory requestFactory =
                new HttpComponentsClientHttpRequestFactory();

        requestFactory.setHttpClient(httpClient);
        var restTemplate = new RestTemplate(requestFactory);

        List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();

        MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter();
        mappingJackson2HttpMessageConverter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
        messageConverters.add(mappingJackson2HttpMessageConverter);
        restTemplate.setMessageConverters(messageConverters);

        return restTemplate;
    }

Окей, ошибка с сертификатами пропала. Формирование самого запроса выглядит так:

public ResponseEntity<AuthResponse> getTokenByLoginPasswordPair(AuthProperties properties) {
    HttpEntity<?> authEntity = createAuthEntity(createGetTokenParams(properties));
    return restTemplate.exchange(
            url,
            HttpMethod.POST,
            authEntity,
            AuthResponse.class
    );
}

private HttpEntity<?> createAuthEntity(MultiValueMap<String, String> params) {
    var httpHeaders = new HttpHeaders();
    httpHeaders.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    return new HttpEntity<>(params, httpHeaders);
}

private MultiValueMap<String, String> createGetTokenParams(AuthProperties properties) {
    MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
    params.add("grant_type", "password");
    params.add("username", properties.getUsername());
    params.add("password", properties.getPassword());
    params.add("client_id", properties.getClientId());
    params.add("resource", URLEncoder.encode(properties.getResource(), StandardCharsets.UTF_8));
    return params;
}

Возвращает уже не JSON c токенами, а HTML-страницу с текстом, сообщающим об ошибке. В RestTemplate.doExecute() на брейкпоинте response = request.execute(); данные request выглядят как ByteArrayOutputStream:

{"grant_type":["password"],"username":["DOMAIN\\username"],"password":["password"],"client_id":["441345C435-23433454V5FC-34TVRVT5VT"],"resource":["https%3A%2F%path%2to%2resource"]}

то есть, идентично запросу из http-клиента. Если отправлять через http-клиент, то такую же страницу об ошибке я получаю, когда отправляю запрос без параметров grant_type=password.

Параметры запросов идентичны тем, которые я шлю через http-клиент идеи. Возможно, я неправильно составляю запрос на отправку application/x-www-form-urlencoded. Возможно, причина, в чём-то другом. Подскажите, что не так? Если надо ещё что-то сообщить из настроек, пишите.


Ответы (0 шт):