web-dev-qa-db-ja.com

RestTemplateを使用したSpring 4.0.0の基本認証

現在、サードパーティアプリケーションとローカルレポートシステムの統合に取り組んでいます。基本認証でREST呼び出しを実装しますが、Spring 4.0.0で問題に直面します。うまく機能する簡単な解決策があります。

final RestTemplate restTemplate = new RestTemplate();
final String plainCreds = "username:password";
final byte[] plainCredsBytes = plainCreds.getBytes();
final byte[] base64CredsBytes = Base64.encodeBase64(plainCredsBytes);
final String base64Creds = new String(base64CredsBytes);

final HttpHeaders headers = new HttpHeaders();
headers.add("Authorization", "Basic " + base64Creds);
final HttpEntity<String> request = new HttpEntity<String>(headers);

final ResponseEntity<MyDto> response = restTemplate.exchange("myUrl", HttpMethod.GET, request, MyDto.class);
final MyDto dot = response.getBody();

しかし、これを書き直して、次のようにClientHttpRequestFactoryを使用したいと考えました。

final RestTemplate restTemplate = new RestTemplate(createSecureTransport("username", "password"));

private ClientHttpRequestFactory createSecureTransport(final String username, final String password) {
    final HttpClient client = new HttpClient();
    final UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(username, password);
    client.getState().setCredentials(new AuthScope(null, 9090, AuthScope.ANY_REALM), credentials);
    return new CommonsClientHttpRequestFactory(client);
}

CommonsClientHttpRequestFactoryクラスがSpring 4.0.0に存在しないため、このコードはコンパイルされていません。誰かがこれに対する代替ソリューションを知っていますか?私はこれでかなり新しいですREST worldしたがって、どんな助けも感謝します。

18
shippi

Spring 4 APIをチェックして、どのクラスが必要なインターフェース、つまり ClientHttpRequestFactory を実装しているかを確認してください。

Javadocからわかるように、おそらく HttpComponentsClientHttpRequestFactory が必要です。これは、ApacheのHttpComponentsのクライアントを使用します。これは、古いcommons HttpClientの後継です。

4
Shaun the Sheep

私はこれが古い質問であることを知っていますが、私はこれに対する答えを自分で探していました。 RestTemplateを構成するときに、RestTemplateインターセプターを追加する必要があります。以下の注釈構成の例:

@Bean
public RestTemplate restTemplate() {

    final RestTemplate restTemplate = new RestTemplate();

    restTemplate.setMessageConverters(Arrays.asList(
            new FormHttpMessageConverter(),
            new StringHttpMessageConverter()
    ));
    restTemplate.getInterceptors().add(new BasicAuthorizationInterceptor("client", "secret"));

    return restTemplate;
}

BasicAuthorizationInterceptor のJavadoc。

私はこれに数時間こだわった。近い将来、誰かを助けるかもしれません。

34
Shiraaz.M

http://www.baeldung.com/2012/04/16/how-to-use-resttemplate-with-basic-authentication-in-spring-3-1/HttpClientで4.3編集

Spring 3.0と3.1、そして現在4.xは、Apache HTTPライブラリを非常によくサポートしています

  1. Spring 3.0CommonsClientHttpRequestFactoryは現在と統合されています寿命のあるHttpClient 3.xの終わり
  2. Spring 3.1現在のHttpClient 4.xのサポートを導入HttpComponentsClientHttpRequestFactory経由( JIRA SPR-618 でサポートを追加)
  3. Spring 4.0導入非同期サポートHttpComponentsAsyncClientHttpRequestFactory経由

HttpClient 4とSpring 4で設定を始めましょう。

RestTemplateには、HTTPリクエストファクトリ(基本認証をサポートするファクトリ-)が必要です。ただし、HttpComponentsClientHttpRequestFactoryのアーキテクチャが設計されているため、既存のRestTemplateを直接使用することは困難であることが判明します 良好なサポートなし for HttpContext –パズル。したがって、HttpComponentsClientHttpRequestFactoryをサブクラス化し、createHttpContextメソッドをオーバーライドする必要があります:( GitHubのsoluvas-frameworkから取得

package org.soluvas.commons.util;

import Java.net.URI;

import javax.annotation.Nullable;

import org.Apache.http.HttpHost;
import org.Apache.http.auth.AuthScope;
import org.Apache.http.auth.UsernamePasswordCredentials;
import org.Apache.http.client.AuthCache;
import org.Apache.http.client.HttpClient;
import org.Apache.http.client.protocol.HttpClientContext;
import org.Apache.http.impl.auth.BasicScheme;
import org.Apache.http.impl.client.BasicAuthCache;
import org.Apache.http.impl.client.BasicCredentialsProvider;
import org.Apache.http.protocol.HttpContext;
import org.springframework.http.HttpMethod;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;

/**
 * From http://www.baeldung.com/2012/04/16/how-to-use-resttemplate-with-basic-authentication-in-spring-3-1/
 * 
 * <p>And with that, everything is in place – the {@link RestTemplate} will now be able to support the Basic Authentication scheme; a simple usage pattern would be:
 * 
 * <pre>
 * final AuthHttpComponentsClientHttpRequestFactory requestFactory = new AuthHttpComponentsClientHttpRequestFactory(
 *                  httpClient, Host, userName, password);
 * final RestTemplate restTemplate = new RestTemplate(requestFactory);
 * </pre>
 *   
 * And the request:
 *
 * <pre>
 * restTemplate.get("http://localhost:8080/spring-security-rest-template/api/foos/1", Foo.class);
 * </pre>
 * 
 * @author anton
 */
public class AuthHttpComponentsClientHttpRequestFactory extends
        HttpComponentsClientHttpRequestFactory {

    protected HttpHost Host;
    @Nullable
    protected String userName;
    @Nullable
    protected String password;

    public AuthHttpComponentsClientHttpRequestFactory(HttpHost Host) {
        this(Host, null, null);
    }

    public AuthHttpComponentsClientHttpRequestFactory(HttpHost Host, @Nullable String userName, @Nullable String password) {
        super();
        this.Host = Host;
        this.userName = userName;
        this.password = password;
    }

    public AuthHttpComponentsClientHttpRequestFactory(HttpClient httpClient, HttpHost Host) {
        this(httpClient, Host, null, null);
    }

    public AuthHttpComponentsClientHttpRequestFactory(HttpClient httpClient, HttpHost Host, 
            @Nullable String userName, @Nullable String password) {
        super(httpClient);
        this.Host = Host;
        this.userName = userName;
        this.password = password;
    }

    @Override
    protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
       // Create AuthCache instance
        AuthCache authCache = new BasicAuthCache();
        // Generate BASIC scheme object and add it to the local auth cache
        BasicScheme basicAuth = new BasicScheme();
        authCache.put(Host, basicAuth);

        // Add AuthCache to the execution context
        HttpClientContext localcontext = HttpClientContext.create();
        localcontext.setAuthCache(authCache);

        if (userName != null) {
            BasicCredentialsProvider credsProvider = new BasicCredentialsProvider();
            credsProvider.setCredentials(new AuthScope(Host), new UsernamePasswordCredentials(userName, password));
            localcontext.setCredentialsProvider(credsProvider);
        }
        return localcontext;        
    }

}

ここで、HttpContextの作成時に、基本認証サポートが組み込まれています。ご覧のとおり、HttpClient 4.xを使用したプリエンプティブ基本認証の実行少し負担:認証情報がキャッシュされ、この認証キャッシュの設定は非常に手動で直感的ではないのプロセスです。

これで、すべてが整った-RestTemplate基本認証スキームをサポートできるようになります。単純な使用パターンは次のとおりです。

final AuthHttpComponentsClientHttpRequestFactory requestFactory =
    new AuthHttpComponentsClientHttpRequestFactory(
                httpClient, Host, userName, password);
final RestTemplate restTemplate = new RestTemplate(requestFactory);

そしてリクエスト:

restTemplate.get(
    "http://localhost:8080/spring-security-rest-template/api/foos/1",
    Foo.class);

RESTサービス自体を保護する方法についての詳細な議論については、 この記事をご覧ください

18
Anton Kurniawan

Spring 4.3.1以降、 BasicAuthorizationInterceptor を使用する簡単な方法があります。これは、RestTemplateで使用される基礎となるhttpクライアントからも独立しています。

RestTemplateBuilder from spring-boot を使用してBasicAuthorizationInterceptorRestTemplateに追加する例:

@Configuration
public class AppConfig {

    @Bean
    public RestTemplate myRestTemplate(RestTemplateBuilder builder) {
        return builder
                .rootUri("http://my.cool.domain/api/")
                .basicAuthorization("login", "password")
                .build();
    }

}

この方法anymyRestTemplate Beanインスタンスを使用して送信されたリクエストには、指定された基本認証ヘッダーが含まれます。したがって、同じRestTemplate Beanインスタンスを使用して外部ドメインにリクエストを送信しないように注意してください。 rootUriはこれから部分的に保護されますが、RestTemplateインスタンスを使用してリクエストを行うときは常に絶対URLを渡すことができますので、注意してください!

spring-bootを使用していない場合は、 this answerに従って、このインターセプターをRestTemplateに手動で追加することもできます。

6

複雑さよりもシンプルを好む場合は、ヘッダーを設定するだけです

    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Basic " + Base64.getUrlEncoder().encodeToString("myuser:mypass".getBytes(Charset.forName("UTF-8"))));
    HttpEntity<SomeBody> myRequest = new HttpEntity<>(mybody, headers);
    restTemplate.postForEntity(someUrl, myRequest, null);

JDKに同梱されているエンコーディングが冗長すぎる場合は、他にもBase64ライブラリがいくつかあるはずです。

5
gogstad

カスタマイズされた残りのテンプレートに基本認証を設定する別のソリューションがあります。

RestTemplate restTemplate = new RestTemplate();
    HttpHost proxy =null;
    RequestConfig config=null;
    String credentials = this.env.getProperty("uname") + ":" + this.env.getProperty("pwd");
    String encodedAuthorization = Base64.getEncoder().encodeToString(credentials.getBytes());

    Header header = new BasicHeader(HttpHeaders.AUTHORIZATION, "Basic " + encodedAuthorization);
    List<Header> headers = new ArrayList<>();
    headers.add(header);
    // if we need proxy
    if(Boolean.valueOf(env.getProperty("proxyFlag"))){
        proxy = new HttpHost(this.env.getProperty("proxyHost"), Integer.parseInt(env.getProperty("proxyPort")), "http");
        config= RequestConfig.custom().setProxy(proxy).build();
    }else{
        config= RequestConfig.custom().build();
    }


    CloseableHttpClient httpClient = HttpClientBuilder.create().setDefaultRequestConfig(config)
            .setDefaultHeaders(headers).build();

    HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);
    restTemplate.setRequestFactory(factory);

    return restTemplate;
0
Yalamanda