
1. Обзор
В этой статье рассмотрим, как использовать Spring’овый RestTemplate для работы с RESTful-сервисами, защищенными Basic Authentication.
После настройки RestTemplate для работы с Basic Authentication все запросы будут содержать учетные данные, необходимые для выполнения процесса аутентификации. Данные для аутентификации кодируются и записываются в HTTP-заголовок Authorization, который выглядит следующим образом:
Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
2. Настройка RestTemplate
Для получения RestTemplate в контексте Spring, достаточно объявить его как бин. Но Basic Authentication требует ручной конфигурации, поэтому будем использовать 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)); } }
Параметры host и port обычно зависят от окружения: у клиента должна быть возможность определять один набор значений, например, для интеграционного тестирования, а другой для продакшена. Эти значения можно задавать через файлы свойств.
3. Ручное управление HTTP-заголовком Authorization
Заголовок 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<T>(createHeaders(username, password)), clazz);
4. Автоматическое управление HTTP-заголовком Authorization
В Spring 3.0 и 3.1, а теперь и в 4.x встроена хорошая поддержка библиотек Apache HTTP:
-
В 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-запросов, поддерживающая Basic Authentication. Однако напрямую использовать существующий 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 мы добавляем поддержку Basic Authentication. Как видно, упреждающая Basic Authentication с помощью HttpClient 4.x немного обременительна. Информация об аутентификации кэшируется, но настроить вручную этот кэш аутентификации сложно и не интуитивно.
Далее просто добавляем 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-сервиса читайте в этой статье.
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-заголовок Authorization вручную, то нам также потребуется дополнительная библиотека для поддержки кодирования:
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.10</version> </dependency>
6. Заключение
Большинство информации, которую можно найти по RestTemplate и безопасности, все еще не учитывает текущие релизы HttpClient 4.x, даже несмотря на то, что ветка 3.x устарела и Spring’ом не поддерживается. В этой статье мы немного восполнили этот пробел, описав, как настроить Basic Authentication для RestTemplate, и использовать его для запросов к защищенному REST API.
Полный пример кода с RESTful-сервисом вы можете найти на Github.
Все разработчики проходят одинаковый путь в развитии. Приглашаем всех желающих на demo-занятие «Послание про архитектуру приложений самому себе в прошлое», на котором преподаватель OTUS Виталий Куценко расскажет, как избежать нескольких ошибок, которые могут сильно усложнить развитие приложения. Регистрация по ссылке.
ссылка на оригинал статьи https://habr.com/ru/company/otus/blog/655739/
Добавить комментарий