web-dev-qa-db-ja.com

restTemplateを使用して認証ヘッダー付きのGETリクエストを送信する

RestTemplateを使用して、いくつかのAuthorizationヘッダーを含むGETリクエストを送信して、サーバーからリソースを取得する必要があります。

docs を調べた後、GETメソッドのいずれもヘッダーをパラメーターとして受け入れないことに気付きました。受け入れや承認などのヘッダーを送信する唯一の方法は exchange を使用することです方法。

それは非常に基本的なアクションなので、何か不足しているのか、それとも別の簡単な方法がありますか?

63
special0ne

あなたは何も見逃していません。 RestTemplate#exchange(..)は、要求ヘッダーの設定に使用する適切なメソッドです。

例は次のとおりです (POSTを使用しますが、GETに変更し、必要なエンティティを使用します)。

別の例です

GETを使用すると、リクエストエンティティに何も含める必要がないことに注意してください(APIがそれを期待している場合を除き、HTTP仕様に反します)。空の文字列を指定できます。

56

postForObjectHttpEntityと一緒に使用できます。次のようになります。

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メソッドを直接使用することです。 getショートハンドはヘッダーの変更をサポートしていません。

非対称性は一見少し奇妙ですが、おそらくこれはSpringの将来のバージョンで修正されるでしょう。

39
iwein

基本認証、ヘッダー、および例外処理を使用した非常に単純な例を次に示します...

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());
    }
}
18
Dave

これらの答えはすべて、不完全であり、かつ/または手間がかかります。 RestTemplateインターフェースを見ると、ClientHttpRequestFactoryが挿入されているように見えます。そして、そのrequestFactoryを使用して、ヘッダー、ボディ、リクエストparamsのカスタマイズを含むリクエストを作成します。

単一の共有ClientHttpRequestFactoryにインジェクトするには、ユニバーサルRestTemplateが必要です。または、new RestTemplate(myHttpRequestFactory)を介して新しいテンプレートインスタンスを取得する必要があります。

残念ながら、単一のAuthorizationヘッダーを設定したい場合でも、このようなファクトリーを作成するのは簡単ではないように見えますが、一般的な要件を考えるとかなりイライラしますが、少なくとも次の場合は簡単に使用できます、Authorizationヘッダーは、Spring-Security Authorizationオブジェクトに含まれるデータから作成できます。その後、SecurityContextHolder.getContext().getAuthorization()を実行し、必要に応じてnullチェックを使用してヘッダーにデータを設定することにより、すべてのリクエストで送信AuthorizationHeaderを設定するファクトリーを作成できますこれで、そのRestTemplateで行われたすべての発信RESTコールには、正しいAuthorizationヘッダーが含まれます。

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のインターフェースは、それよりもやり取りが困難です。さらに良いのは、既存のファクトリー実装の抽象ラッパーで、それらの機能を1つだけ置き換えるために、AbstractHeaderRewritingRequestFactoryのような単純なオブジェクトのように見えるようにすることです。現在、これらは非常に一般的な目的であるため、これらのラッパーを作成することさえ複雑な研究​​です。

7
ideasculptor