Отправка запроса GET с заголовками аутентификации с использованием restTemplate

Мне нужно получить ресурсы с моего сервера, отправив запрос GET с некоторыми заголовками авторизации, используя RestTemplate.

После перехода docs я заметил, что ни один из методов GET не принимает заголовки в качестве параметра, и единственный способ отправки заголовков, таких как принятие и авторизация с помощью метода exchange.

Поскольку это очень основное действие, мне интересно, не хватает ли я чего-то и есть ли еще один, более простой способ сделать это?

Ответ 1

Вы ничего не пропустили. RestTemplate#exchange(..) - это соответствующий метод, используемый для установки заголовков запросов.

Вот пример (с POST, но просто измените его, чтобы ПОЛУЧИТЬ и использовать желаемый объект).

Вот еще один пример.

Обратите внимание, что с помощью GET ваш объект запроса не должен содержать ничего (если только ваш API этого не ожидает, но это противоречит спецификации HTTP). Это может быть пустая строка.

Ответ 2

Вы можете использовать postForObject с HttpEntity. Это будет выглядеть так:

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", "Bearer "+accessToken);

HttpEntity<String> entity = new HttpEntity<String>(requestJson,headers);
String result = restTemplate.postForObject(url, entity, String.class);

В запросе GET вы обычно не отправляете тело (оно разрешено, но оно не служит никакой цели). Способ добавления заголовков без подключения RestTemplate по-разному заключается в непосредственном использовании методов exchange или execute. Получающие сокращения не поддерживают модификацию заголовка.

Асимметрия на первый взгляд немного странная, возможно, это будет исправлено в будущих версиях Spring.

Ответ 3

Вот очень простой пример с базовой аутентификацией, заголовками и обработкой исключений...

private HttpHeaders createHttpHeaders(String user, String password)
{
    String notEncoded = user + ":" + password;
    String encodedAuth = "Basic " + Base64.getEncoder().encodeToString(notEncoded.getBytes());
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_JSON);
    headers.add("Authorization", encodedAuth);
    return headers;
}

private void doYourThing() 
{
    String theUrl = "http://blah.blah.com:8080/rest/api/blah";
    RestTemplate restTemplate = new RestTemplate();
    try {
        HttpHeaders headers = createHttpHeaders("fred","1234");
        HttpEntity<String> entity = new HttpEntity<String>("parameters", headers);
        ResponseEntity<String> response = restTemplate.exchange(theUrl, HttpMethod.GET, entity, String.class);
        System.out.println("Result - status ("+ response.getStatusCode() + ") has body: " + response.hasBody());
    }
    catch (Exception eek) {
        System.out.println("** Exception: "+ eek.getMessage());
    }
}

Ответ 4

Все эти ответы кажутся неполными и/или kludges. Рассматривая интерфейс RestTemplate, он уверен, что он предназначен для ввода ClientHttpRequestFactory в него, а затем этот запросFactory будет использоваться для создания запроса, включая любые настройки параметров заголовков, тела и запроса.

Вам понадобится универсальный ClientHttpRequestFactory для вставки в один общий RestTemplate или вам нужно получить новый экземпляр шаблона через new RestTemplate(myHttpRequestFactory).

К сожалению, для создания такого factory выглядит несколько нетривиально, даже если вы просто хотите установить один заголовок авторизации, что довольно неприятно, учитывая то, что обычно является общим требованием, но по крайней мере оно позволяет легко используйте, если, например, ваш заголовок авторизации может быть создан из данных, содержащихся в объекте Spring -Security Authorization, тогда вы можете создать factory, который устанавливает исходящий авторизатор авторизации для каждого запроса, делая SecurityContextHolder.getContext().getAuthorization(), а затем заполнение заголовка с нулевыми проверками. Теперь все исходящие вызовы отдыха, сделанные с помощью этого RestTemplate, будут иметь правильный заголовок авторизации.

Без особого внимания к механизму HttpClientFactory, предоставляя простые базовые классы перегрузки для обычных случаев, таких как добавление одного заголовка в запросы, большинство удобных методов RestTemplate в конечном итоге становятся пустой тратой времени, поскольку их можно использовать редко.

Я хотел бы увидеть что-то простое, как это сделало доступным

@Configuration
public class MyConfig {
  @Bean
  public RestTemplate getRestTemplate() {
    return new RestTemplate(new AbstractHeaderRewritingHttpClientFactory() {
        @Override
        public HttpHeaders modifyHeaders(HttpHeaders headers) {
          headers.addHeader("Authorization", computeAuthString());
          return headers;
        }
        public String computeAuthString() {
          // do something better than this, but you get the idea
          return SecurityContextHolder.getContext().getAuthorization().getCredential();
        }
    });
  }
}

В настоящий момент интерфейс доступной ClientHttpRequestFactory сложнее взаимодействовать с этим. Еще лучше будет абстрактная оболочка для существующих реализаций factory, которая делает их похожими на более простой объект, такой как AbstractHeaderRewritingRequestFactory, с целью замены только одной части функциональности. Прямо сейчас, они являются очень общей целью, так что даже написание этих оберток является сложным исследованием.