Найти тему

Обычная проверка подлинности с помощью RestTemplate

Оглавление

1. Общий обзор

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

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

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

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

Мы можем загрузить RestTemplate в контекст Spring, просто объявив для него bean; однако для настройки RestTemplate с базовой аутентификацией потребуется ручное вмешательство, поэтому вместо прямого объявления bean мы будем использовать 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.
  • В 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);

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

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

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

<dependency>
<groupId>org.apache.httpcomponents.client5</groupId>
<artifactId>httpclient5</artifactId>
<version>5.2.1</version>
</dependency>

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

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

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

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

Оригинал статьи: https://www.baeldung.com/how-to-use-resttemplate-with-basic-authentication-in-spring