RestTemplate базовая или дайджест-аутентификация с текущим httpclient (4.x) - PullRequest
10 голосов
/ 21 февраля 2012

Я пытаюсь сделать дайджест в основном (или базовую) аутентификацию, используя RestTemplate и httpclient (4.x) .

Поскольку я не смог найти ни одного уместного примера того, как на самом деле это сделать, я попытался различными способами перехватить различные артефакты httpclient, но безуспешно - по сути, нет заголовка Authentication отправлено вообще.

Моя текущая реализация:

DefaultHttpClient newHttpClient = new DefaultHttpClient();
Credentials credentials = new UsernamePasswordCredentials( username, password );
AuthScope authScope = new AuthScope( host, port, AuthScope.ANY_REALM );
BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials( authScope, credentials );
newHttpClient.setCredentialsProvider( credentialsProvider );

HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory( newHttpClient );
restTemplate.setRequestFactory( requestFactory );

Есть ли что-то, что я делаю не так?Есть ли где-нибудь рабочий пример для этого?Любая помощь приветствуется.Благодарю.

Ответы [ 3 ]

9 голосов
/ 30 марта 2012

Попробуйте реализовать свою собственную RequestFactory для достижения упреждающей аутентификации.

public class PreEmptiveAuthHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {

public PreEmptiveAuthHttpRequestFactory(DefaultHttpClient client) {
    super(client);
}

@Override
protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
    AuthCache authCache = new BasicAuthCache();
    BasicScheme basicAuth = new BasicScheme();
    HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort());
    authCache.put(targetHost, basicAuth);
    BasicHttpContext localcontext = new BasicHttpContext();
    localcontext.setAttribute(ClientContext.AUTH_CACHE, authCache);

    return localcontext;
}
}

А затем просто используйте его:

HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory( newHttpClient );

Надеюсь, это поможет


как установить имя пользователя и пароль (скопировано из комментария @ bifur)

Вы можете использовать UserNamePasswordCredentials

UsernamePasswordCredentials credentials = new UsernamePasswordCredentials(getUsername(),getPassword()); 
client.getCredentialsProvider().setCredentials(new AuthScope(getHost(), getPort(), AuthScope.ANY_REALM), credentials); 

И просто использовать клиент в предыдущемфабрика

HttpComponentsClientHttpRequestFactory requestFactory = new PreEmptiveAuthHttpRequestFactory(client);
1 голос
/ 28 октября 2018

С последней версией Spring и HttpClient они действительно упростили как базовую, так и дайджест-проверку подлинности.

Примечание. Я использую Spring Boot 2.xx (Spring Framework5.xx) и HttpClient 4.5.x


Настройка RestTemplate

Мы можем настроить RestTemplate для выполнения preemptive или Непрерывная (по умолчанию) базовая или дайджест-аутентификация.

Неприоритетная базовая или дайджест-настройка аутентификации

Настройка для RestTemplate для использования неупреждающая (т. е. изначально выполняющая запрос на вызов) базовая или дайджест-проверка подлинности одинакова.Просто введите имя пользователя и пароль через класс CredentialsProvider библиотеки HttpClient.

HttpClient автоматически определяет, какой тип аутентификации использует сервер, на основе заголовка ответа 401 первоначального запроса (запроса вызова), таким образом, нет необходимости выполнять какую-либо конфигурацию, специфичную для типа аутентификации.

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    Credentials credentials = new UsernamePasswordCredentials(username, password);
    CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
    credentialsProvider.setCredentials(AuthScope.ANY, credentials);

    HttpClient httpClient = HttpClients
            .custom()
            .setDefaultCredentialsProvider(credentialsProvider)
            .build();

    return builder
            .requestFactory(() -> new HttpComponentsClientHttpRequestFactory(httpClient))
            .build();
}

Preemptive Basic Auth Setup

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

@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
    return builder
            .basicAuthorization(username, password)
            .build();
}

Настройка проверки подлинности дайджеста

Spring не поддерживает встроенную аутентификацию дайджеста для RestTemplate из коробки.Поскольку для дайджест-аутентификации требуются одноразовые и, возможно, другие данные, сгенерированные сервером (например, непрозрачные), помимо имени пользователя и пароля, для аутентификации себя, поэтому необходимо выполнить хотя бы один запрос на вызов.

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

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


Отправка запроса с использованием RestTemplate

При использовании RestTemplate для отправки запроса вам не требуется обработка, зависящая от типа аутентификации.Не имеет значения, используете ли вы приоритетную или не преимущественную проверку подлинности, код для отправки запросов будет таким же.

Пример запроса GET

String response = restTemplate.getForObject(url, String.class);
JSONObject result = new JSONObject(response);

Образец запроса POST

JSONObject body = new JSONObject();
// populate body

HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);

HttpEntity<String> request = new HttpEntity<>(body, headers);
String response = restTemplate.postForObject(url, request, String.class);
JSONObject result = new JSONObject(response);
0 голосов
/ 21 сентября 2016

Я немного изменил исходный ответ:

  • добавлена ​​поддержка https
  • обновлен устаревший материал

    public class PreEmptiveAuthHttpRequestFactory extends HttpComponentsClientHttpRequestFactory {
    
        public PreEmptiveAuthHttpRequestFactory(HttpClient client) {
            super(client);
        }
    
        @Override
        protected HttpContext createHttpContext(HttpMethod httpMethod, URI uri) {
            AuthCache authCache = new BasicAuthCache();
            BasicScheme basicAuth = new BasicScheme();
            HttpHost targetHost = new HttpHost(uri.getHost(), uri.getPort(), uri.getScheme());
            authCache.put(targetHost, basicAuth);
            HttpClientContext localContext = HttpClientContext.create();
            localContext.setAuthCache(authCache);
            return localContext;
        }
    }
    
...