RestTemplateを使用した基本認証
目次
1. 概要
この記事では、SpringsRestTemplateからconsume a RESTful Service secured with Basic Authenticationの使用方法を示します。
テンプレートに基本認証が設定されると、認証プロセスの実行に必要なpreemptively containing the full credentialsが各要求に送信されます。 資格情報はエンコードされ、基本認証スキームの仕様に従ってAuthorizationHTTPヘッダーを使用します。 例は次のようになります。
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
参考文献:
2. RestTemplateの設定
RestTemplateをSpringコンテキストにブートストラップすることは、そのBeanを宣言するだけで実行できます。ただし、RestTemplateをBasic Authenticationで設定するには手動による介入が必要になるため、Beanを直接宣言する代わりに、SpringFactoryBeanを使用して柔軟性を高めます。 このファクトリは、初期化時にテンプレートを作成および構成します。
@Component
public class RestTemplateFactory
implements FactoryBean, InitializingBean {
private RestTemplate restTemplate;
public RestTemplate getObject() {
return restTemplate;
}
public Class getObjectType() {
return RestTemplate.class;
}
public boolean isSingleton() {
return true;
}
public void afterPropertiesSet() {
HttpHost host = new HttpHost("localhost", 8082, "http");
restTemplate = new RestTemplate(
new HttpComponentsClientHttpRequestFactoryBasicAuth(host));
}
}
hostとportの値は環境に依存する必要があります。これにより、クライアントは、統合テスト用と本番用の値のセットを柔軟に定義できます。 値はfirst class Spring support for properties filesで管理できます。
3. 承認HTTPヘッダーの手動管理
Authorizationヘッダーを作成するプロセスは、基本認証では比較的簡単なので、数行のコードでほとんど手動で行うことができます。
HttpHeaders createHeaders(String username, String password){
return new HttpHeaders() {{
String auth = username + ":" + password;
byte[] encodedAuth = Base64.encodeBase64(
auth.getBytes(Charset.forName("US-ASCII")) );
String authHeader = "Basic " + new String( encodedAuth );
set( "Authorization", authHeader );
}};
}
その後、リクエストを送信するのも同じくらい簡単になります。
restTemplate.exchange
(uri, HttpMethod.POST, new HttpEntity(createHeaders(username, password)), clazz);
4. 承認HTTPヘッダーの自動管理
Spring 3.0と3.1、そして現在4.xは、Apache HTTPライブラリを非常によくサポートしています。
-
Spring 3.0、CommonsClientHttpRequestFactoryが現在のend-of-life’dHttpClient 3.xと統合されました
-
Spring 3.1では、HttpComponentsClientHttpRequestFactoryを介して現在のHttpClient 4.xのサポートが導入されました(JIRASPR-6180でサポートが追加されました)
-
Spring 4.0では、HttpComponentsAsyncClientHttpRequestFactoryを介した非同期サポートが導入されました
HttpClient 4とSpring 4で設定を始めましょう。
RestTemplateには、これまでのところ、HTTP要求ファクトリ(基本認証をサポートするファクトリ)が必要です。 ただし、RestTemplateのアーキテクチャはHttpContext用にwithout good supportとして設計されているため、既存のHttpComponentsClientHttpRequestFactoryを直接使用することは困難です。これはパズルの道具です。 したがって、HttpComponentsClientHttpRequestFactoryをサブクラス化し、createHttpContextメソッドをオーバーライドする必要があります。
public class HttpComponentsClientHttpRequestFactoryBasicAuth
extends HttpComponentsClientHttpRequestFactory {
HttpHost host;
public HttpComponentsClientHttpRequestFactoryBasicAuth(HttpHost host) {
super();
this.host = host;
}
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
return createHttpContext();
}
private HttpContext createHttpContext() {
AuthCache authCache = new BasicAuthCache();
BasicScheme basicAuth = new BasicScheme();
authCache.put(host, basicAuth);
BasicHttpContext localcontext = new BasicHttpContext();
localcontext.setAttribute(HttpClientContext.AUTH_CACHE, authCache);
return localcontext;
}
}
基本認証サポートが組み込まれているのは、ここ(HttpContextの作成)です。 ご覧のとおり、HttpClient 4.xでプリエンプティブ基本認証を実行するのはa bit of a burdenです。認証情報はキャッシュされ、この認証キャッシュを設定するプロセスは非常に手動で直感的ではありません。
これで、すべてが整いました。BasicAuthorizationInterceptorを追加するだけで、RestTemplateが基本認証スキームをサポートできるようになります。
restTemplate.getInterceptors().add(
new BasicAuthorizationInterceptor("username", "password"));
そしてリクエスト:
restTemplate.exchange(
"http://localhost:8082/spring-security-rest-basic-auth/api/foos/1",
HttpMethod.GET, null, Foo.class);
RESTサービス自体を保護する方法の詳細については、check out this articleを参照してください。
5. Mavenの依存関係
RestTemplate自体とHttpClientライブラリには、次のMaven依存関係が必要です。
org.springframework
spring-webmvc
5.0.6.RELEASE
org.apache.httpcomponents
httpclient
4.5.3
オプションで、HTTPAuthorizationヘッダーを手動で作成する場合は、エンコードをサポートするために追加のライブラリが必要です。
commons-codec
commons-codec
1.10
最新バージョンはMaven repositoryにあります。
6. 結論
Apache HttpClientの開発の3.xブランチはしばらくの間サポートが終了し、そのバージョンのSpringサポートは完全に非推奨になりましたが、RestTemplateとセキュリティに記載されている情報の多くはまだthe current HttpClient 4.xリリースを考慮していません。 この記事は、RestTemplateを使用して基本認証を設定する方法と、それを使用してセキュリティで保護されたREST APIを使用する方法について、詳細なステップバイステップの説明を通じてこれを変更する試みです。
ここで検討した消費側と実際のRESTfulサービスの両方を実装した記事のコードサンプルを超えるには、プロジェクトover on Github.を参照してください。
これはMavenベースのプロジェクトであるため、そのままインポートして実行するのは簡単です。