Перейти к основному содержимому

Базовая аутентификация с RestTemplate

· 4 мин. чтения

Оглавление

1. Обзор

В этом руководстве мы узнаем, как использовать Spring RestTemplate для использования службы RESTful, защищенной с помощью базовой аутентификации .

После того, как мы настроим обычную аутентификацию для шаблона, каждый запрос будет отправляться заранее, содержащий полные учетные данные , необходимые для выполнения процесса аутентификации. Учетные данные будут закодированы и будут использовать HTTP- заголовок авторизации в соответствии со спецификациями схемы базовой аутентификации. Пример будет выглядеть так:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

2. Настройка RestTemplate

Мы можем загрузить RestTemplate в контекст Spring, просто объявив для него bean-компонент; однако настройка RestTemplate с базовой аутентификацией потребует ручного вмешательства, поэтому вместо прямого объявления компонента мы будем использовать Spring FactoryBean для большей гибкости. Этот FactoryBean создаст и настроит шаблон при инициализации:

@Component
public class RestTemplateFactory
implements FactoryBean<RestTemplate>, InitializingBean {

private RestTemplate restTemplate;

public RestTemplate getObject() {
return restTemplate;
}
public Class<RestTemplate> 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));
}
}

Значения хоста и порта должны зависеть от среды, что позволяет клиенту гибко определять один набор значений для интеграционного тестирования, а другой — для производственного использования. Значения могут управляться первоклассной поддержкой Spring для файлов свойств .

3. Ручное управление HTTP-заголовком авторизации

Для нас довольно просто создать заголовок авторизации для базовой аутентификации, поэтому мы можем сделать это вручную с помощью нескольких строк кода:

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<T>(createHeaders(username, password)), clazz);

4. Автоматическое управление HTTP-заголовком авторизации

Spring 3.0 и 3.1, а теперь и 4.x имеют очень хорошую поддержку HTTP-библиотек Apache:

  • В Spring 3.0 CommonsClientHttpRequestFactory интегрировался с HttpClient 3.x , срок службы которого уже истек. ``
  • В Spring 3.1 появилась поддержка текущего HttpClient 4.x через HttpComponentsClientHttpRequestFactory (поддержка добавлена в JIRA SPR-6180 ).
  • В Spring 4.0 появилась асинхронная поддержка через HttpComponentsAsyncClientHttpRequestFactory.

Давайте начнем настройку с HttpClient 4 и Spring 4.

Для RestTemplate потребуется фабрика HTTP-запросов, поддерживающая обычную аутентификацию. Однако прямое использование существующей HttpComponentsClientHttpRequestFactory окажется затруднительным, поскольку архитектура RestTemplate была разработана без хорошей поддержки HttpContext , важной части головоломки. Таким образом, нам нужно создать подкласс 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 для нас немного обременительно. Информация об аутентификации кэшируется, и нам очень сложно настроить этот кэш аутентификации вручную и неинтуитивно.

Теперь, когда все готово, RestTemplate сможет поддерживать схему базовой аутентификации, просто добавив BasicAuthorizationInterceptor:

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, ознакомьтесь с этой статьей .

5. Зависимости Maven

Нам потребуются следующие зависимости Maven для самого RestTemplate и для библиотеки HttpClient:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>

<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>4.5.3</version>
</dependency>

При желании, если мы создадим заголовок авторизации HTTP вручную, нам потребуется дополнительная библиотека для поддержки кодирования:

<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.10</version>
</dependency>

Самые свежие версии мы можем найти в репозитории Maven .

6. Заключение

Большая часть информации, которую можно найти в RestTemplate и безопасности, по-прежнему не учитывает текущие выпуски HttpClient 4.x, даже несмотря на то, что ветка 3.x устарела, а поддержка этой версии Spring полностью устарела. . В этой статье мы попытаемся изменить это, пройдя подробное пошаговое обсуждение того, как настроить обычную аутентификацию с помощью RestTemplate и использовать его для использования защищенного REST API.

Чтобы выйти за рамки примеров кода в этой статье с реализацией потребляющей стороны и реальной службы RESTful, взгляните на проект на Github.

Это проект на основе Maven, поэтому его легко импортировать и запускать как есть.