Использование Apache HttpContents для http-запросов с аутентификацией NTLM

#coldfusion #coldfusion-9 #apache-httpclient-4.x

#coldfusion #coldfusion-9 #apache-httpclient-4.x

Вопрос:

Краткая справка.

CFHTTP не поддерживает аутентификацию Windows NTLM / Authenticate, только базовую аутентификацию. Мне нужно делать http-запросы, которые должны будут проходить аутентификацию в NTLM, поэтому я закончил тем, что запустил свою собственную версию CFHTTP.

Я нашел статью Терри Райана, в которой используется apache httpclient версии 3.1 для выполнения дайджест-аутентификации, и основывался на этом, используя вместо этого версию 4.1.2, которая включает функциональность NTLM.

У меня есть функция, которая будет выполнять запрос get, а затем другие функции для обработки возврата структуры, которая выглядит как набор результатов cfhttp. Внесенные мной изменения основаны на примере учебника по аутентификации.

 public any function httpRequest(url,username,password,domain) {
    var httpClient = createObject("java","org.apache.http.impl.client.DefaultHttpClient");
    var authScope = createObject("java","org.apache.http.auth.AuthScope");
    var httpCredentials = createObject("java","org.apache.http.auth.NTCredentials");
    var httpGet = createObject("java","org.apache.http.client.methods.HttpGet");
    var jURL = createObject("java", "java.net.URL").init(arguments.url);
    var host = jURL.getHost();
    var path = jURL.getPath();
    var httpHostTarget = createObject("java","org.apache.http.HttpHost").init(host,80,"http");
    var localContext = createObject("java","org.apache.http.protocol.BasicHttpContext");
    var httpContent = {};
    var response = '';

    if (len(arguments.username) and len(arguments.password) gt 0){
        httpCredentials.init(arguments.Username, arguments.password, cgi.remote_host,arguments.domain);
        httpClient.getCredentialsProvider().setCredentials(authScope.ANY, httpCredentials);
    }

    if (!Len(path)) path = "/";
    httpGet.init(path);

    response = httpClient.execute(httpHostTarget, httpget, localContext);

    httpContent = convertHttpClientResponseToCFHTTPFormat(response);

    httpClient.getConnectionManager().shutdown();

    return httpContent;
}
 

Это работало нормально, пока я не изменил функцию для выполнения аутентификации.

К сожалению, теперь я получаю :

Метод execute не найден.

Либо нет методов с указанным именем метода и типами аргументов, либо метод execute перегружен типами аргументов, которые ColdFusion не может надежно расшифровать. ColdFusion нашел 2 метода, которые соответствуют предоставленным аргументам. Если это объект Java, и вы подтвердили, что метод существует, используйте функцию javacast для уменьшения неоднозначности.

Насколько я могу судить, в HttpClient есть только одна соответствующая функция execute() для переданных ей классов объектов, поэтому я немного смущен. JavaCast не позволяет выполнять приведение к сложным объектам или супертипам, так что это не сработало.

Может кто-нибудь подсказать, как я могу заставить это работать? Как я могу уменьшить двусмысленность?

Ответ №1:

Глядя на ошибку, она путается между двумя методами выполнения, которые имеют одинаковое количество параметров. Хотя я не знаю, почему это так…

В любом случае, я нашел способ обойти ошибку. Это включает в себя извлечение метода, который вам нужен, из класса и вызов его напрямую. Если бы ColdFusion был более доволен приведением объектов Java, жизнь могла бы быть проще.

 //response = httpClient.execute(httpHostTarget, httpget, localContext);

classes = [httpHostTarget.getClass(), CreateObject('java', 'org.apache.http.HttpRequest').getClass(), CreateObject('java', 'org.apache.http.protocol.HttpContext').getClass()];
method = httpClient.getClass().getMethod('execute', classes);
params = [httpHostTarget, httpget, localContext];
response = method.invoke(httpClient, params);
 

Может быть другой способ сделать это (вместо этого кастинг), но это все, что у меня есть 😉

Комментарии:

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

Ответ №2:

Как предположение, вы могли загружать неправильную версию .jars? Похоже, вы не используете JavaLoader, как Райан…

Комментарии:

1. Я как бы обошел всю ошибку JavaLoader, сбросив jar-файлы из http core и client в папку jre / lib / ext на сервере. глядя на методы выполнения объекта httpclient, я могу выбрать тот, который я хочу вызвать, и мои типы объектов для httpHostTarget, httpget и localContext совпадают с ожидаемыми для этого метода и никакими другими, но все же он выдает эту ошибку.

2. @Stephen — В ошибке указано, что найдено два ( 2 ) метода. Я не вижу двух (2) методов, которые соответствуют этой подписи. Если я не пропускаю унаследованный класс .. ?

3. @Leigh Да. Это именно та проблема, с которой я столкнулся. Я вижу только один соответствующий метод. Однако существует 2 метода выполнения с 3 параметрами. Эти методы имеют разные классы для параметров.

4. @Stephen — Не повторять очевидное 😉 .. но что-то кажется подозрительным в том, как CF обнаруживает подписи. Вы знаете, какую версию CF использовал Терри? Потому что я пробовал как его, так и ваш подход (ie jre/lib/ext ) с CF9, и ни один из них не сработал. Я даже не мог вызвать этот метод с отражением Java, что странно.

5. 2009 предложил бы ColdFusion 8 — я на CF 9.0.1. Сегодня мы с коллегой обнаружили, что если вы удаляете локальный контекст, функция выполняется, но мы не можем получить учетные данные для передачи.