RestTemplate: ошибка при отправке приложения / x- www-form-urlencoded - PullRequest
0 голосов

Мне нужно получить jwt-токен по логин-паролю.

curl выглядит вот так:

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'

Я выполняю запрос с http-клиентом IDEA, он выглядит вот так:

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

Я получил токены, выполнив этот запрос, без проблем. Но мне нужно сделать это с помощью RestTemplate. Мне нужен был локально подписанный сертификат, мой bean-компонент restTemplate выглядит вот так:

@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;
}

Я получил html -страницу с сообщением об ошибке. Когда RestTemplate.doExecute () остановился на точке останова response = request.execute();, запрос выглядит как ByteArrayOutputStream:

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

, идентично запросу HTTP-клиента IDEA. В случае запроса http-клиента я получаю ту же страницу с ошибкой при попытке отправить

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

без grant_type=password.

Может быть, я неправильно оформляю форму application/x-www-form-urlencoded? Пожалуйста, помогите.

...