使用 Apache HttpComponents 进行 NTLM 身份验证的 http 请求

发布于 2024-12-13 09:23:10 字数 2248 浏览 1 评论 0原文

快速背景。

CFHTTP 不支持 Windows NTLM/Authenticate 身份验证,仅支持基本身份验证。我需要发出必须针对 NTLM 进行身份验证的 http 请求,因此我最终推出了自己的 CFHTTP 版本。

我发现 Terry Ryan 的文章 使用 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;
}

在我更改执行身份验证的功能之前,它工作得很好。

不幸的是我现在得到:

未找到执行方法。

要么不存在具有指定方法名称和参数类型的方法,要么执行方法重载了 ColdFusion 无法可靠解析的参数类型。 ColdFusion 找到了 2 个与提供的参数匹配的方法。如果这是一个 Java 对象并且您验证了该方法存在,请使用 javacast 函数来减少歧义。

据我所知,对于传递给它的对象类,HttpClient 中只有一个匹配的execute() 函数,所以我有点困惑。 JavaCast 不允许您转换为复杂对象或超类型,因此这不起作用。

谁能建议我如何让它发挥作用?我怎样才能减少歧义?

Quick background.

CFHTTP doesn't support Windows NTLM/Authenticate authentication, only basic authentication. I need to make http requests that will have to authenticate against NTLM, so I've ended up rolling my own version of CFHTTP.

I found Terry Ryan's article that uses the apache httpclient version 3.1 to perform digest authentication and have built upon that using version 4.1.2 instead which includes NTLM functionality.

I have a function that will perform a get request and then other functions to handle returning a structure that looks like the cfhttp result set. The changes I made are based on the authentication tutorial example.

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;
}

This was working fine until I altered the function to perform the authentication.

Unfortunately I'm now getting :

The execute method was not found.

Either there are no methods with the specified method name and argument types or the execute method is overloaded with argument types that ColdFusion cannot decipher reliably. ColdFusion found 2 methods that match the provided arguments. If this is a Java object and you verified that the method exists, use the javacast function to reduce ambiguity.

As far as I can tell there is only one matching execute() function in HttpClient for the object classes passed to it, so I'm a little confused. JavaCast doesn't allow you to cast to complex objects or super types, so that didn't work.

Can anyone suggest how I can get this to work? How can I reduce the ambiguity?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦纸 2024-12-20 09:23:10

查看错误,两个具有相同数量参数的执行方法会变得混乱。虽然我不知道为什么......

无论如何,我找到了解决该错误的方法。它涉及将您需要的方法从类中取出并直接调用它。如果 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);

可能还有另一种方法可以做到这一点(改为铸造),但这就是我所拥有的;)

Looking at the error, it's getting confused between two execute methods that have the same number of parameters. Although I don't know why it is...

Anyway, I found a way around the error. It involves pulling the method you're after out of the class and invoking it directly. If ColdFusion was happier with casting Java objects life might be easier.

//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);

There may be another way of doing this (casting instead) but it's all I've got ;)

陪我终i 2024-12-20 09:23:10

作为猜测,您是否加载了错误版本的 .jars ?您似乎没有像 Ryan 那样使用 JavaLoader...

As a guess, could you be loading the wrong version of the .jars ? You don't seem to be using JavaLoader like Ryan did...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文