在使用NTLM进行身份验证时,HttpClient 4.1.1返回401,浏览器工作正常 [英] HttpClient 4.1.1 returns 401 when authenticating with NTLM, browsers work fine

查看:1617
本文介绍了在使用NTLM进行身份验证时,HttpClient 4.1.1返回401,浏览器工作正常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用Apache / Jakarta HttpClient 4.1.1使用给定的凭据连接到任意网页。为了测试这一点,我在运行的dev机器上安装了最少的IIS 7.5,其中一次只有一种身份验证模式处于活动状态。基本身份验证工作正常,但每当我尝试登录时,Digest和NTLM都会返回401错误消息。这是我的代码:

I'm trying to use the Apache/Jakarta HttpClient 4.1.1 to connect to an arbitrary web page using the given credentials. To test this, I have a minimal install of IIS 7.5 on my dev machine running where only one authentication mode is active at a time. Basic authentication works fine, but Digest and NTLM return 401 error messages whenever I try to log in. Here is my code:

    DefaultHttpClient httpclient = new DefaultHttpClient();
    HttpContext localContext = new BasicHttpContext();
    HttpGet httpget = new HttpGet("http://localhost/"); 
    CredentialsProvider credsProvider = new BasicCredentialsProvider();
    credsProvider.setCredentials(AuthScope.ANY,
            new NTCredentials("user", "password", "", "localhost"));
    if (!new File(System.getenv("windir") + "\\krb5.ini").exists()) {
        List<String> authtypes = new ArrayList<String>();
        authtypes.add(AuthPolicy.NTLM);
        authtypes.add(AuthPolicy.DIGEST);
        authtypes.add(AuthPolicy.BASIC);
        httpclient.getParams().setParameter(AuthPNames.PROXY_AUTH_PREF,
                authtypes);
        httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF,
                authtypes);
    }
    localContext.setAttribute(ClientContext.CREDS_PROVIDER, credsProvider);
    HttpResponse response = httpclient.execute(httpget, localContext);
    System.out.println("Response code: " + response.getStatusLine());

我在Fiddler中注意到的一件事是Firefox和HttpClient发送的哈希值不同,让我觉得IIS 7.5可能期望比HttpClient提供更强的散列?有任何想法吗?如果我能够验证这适用于NTLM,那就太棒了。摘要也会很好,但如果有必要,我可以不用它。

The one thing I've noticed in Fiddler is that the hashes sent by Firefox versus by HttpClient are different, making me think that maybe IIS 7.5 is expecting stronger hashing than HttpClient provides? Any ideas? It'd be great if I could verify that this would work with NTLM. Digest would be nice too, but I can live without that if necessary.

推荐答案

我不是这方面的专家,但在此期间使用http组件的NTLM身份验证我已经看到,在我的情况下,客户端需要3次尝试才能连接到NTML端点。它是有点儿描述这里 。SPNEGO但它是用于NTLM认证有点不同

I am not an expert on the subject but during the NTLM authentication using http components I have seen that the client needs 3 attempts in order to connect to an NTML endpoint in my case. It is kinda described here for Spnego but it is a bit different for the NTLM authentication.

有关NTLM在第一次尝试的客户端将与目标身份验证状态的请求:未攻击和Web服务器返回HTTP 401状态和标题: WWW-Authenticate:NTLM

For NTLM in the first attempt client will make a request with Target auth state: UNCHALLENGED and Web server returns HTTP 401 status and a header: WWW-Authenticate: NTLM

客户端将检查配置的身份验证方案,NTLM应在客户端代码中配置。

Client will check for the configured Authentication schemes, NTLM should be configured in client code.

第二次尝试,客户端将使用目标身份验证发出请求状态:挑战,并且将发送授权报头与以base64格式编码的令牌:授权:再次NTLM TlRMTVNTUAABAAAAAYIIogAAAAAoAAAAAAAAACgAAAAFASgKAAAADw ==
服务器返回HTTP 401状态但标题: WWW-Authenticate:NTLM 现在填充了编码信息。

Second attempt, client will make a request with Target auth state: CHALLENGED, and will send an authorization header with a token encoded in base64 format: Authorization: NTLM TlRMTVNTUAABAAAAAYIIogAAAAAoAAAAAAAAACgAAAAFASgKAAAADw== Server again returns HTTP 401 status but the header: WWW-Authenticate: NTLM now is populated with encoded information.

第三次尝试客户端将使用 WWW-Authenticate:NTLM 标头中的信息,并将使用目标身份验证状态:HANDSHAKE 和授权标头授权:NTLM 其中包含服务器的更多信息。

3rd Attempt Client will use the information from WWW-Authenticate: NTLM header and will make the final request with Target auth state: HANDSHAKE and an authorisation header Authorization: NTLM which contains more information for the server.

在我的情况下,我收到 HTTP / 1.1 200 OK 之后。

In my case I receive an HTTP/1.1 200 OK after that.

为了在每个请求中避免所有这些文档指出必须将相同的执行令牌用于逻辑相关的请求。对我来说它没用。

In order to avoid all this in every request documentation at chapter 4.7.1 states that the same execution token must be used for logically related requests. For me it did not worked.

我的代码:
我在 @PostConstruct EJB的方法

My code: I initialize the client once in a @PostConstruct method of an EJB

        PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
        cm.setMaxTotal(18);
        cm.setDefaultMaxPerRoute(6);

        RequestConfig requestConfig = RequestConfig.custom()
        .setSocketTimeout(30000)
        .setConnectTimeout(30000)
        .setTargetPreferredAuthSchemes(Arrays.asList(AuthSchemes.NTLM))
        .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))
        .build();

        CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new NTCredentials(userName, password, hostName, domainName));

        // Finally we instantiate the client. Client is a thread safe object and can be used by several threads at the same time. 
        // Client can be used for several request. The life span of the client must be equal to the life span of this EJB.
         this.httpclient = HttpClients.custom()
        .setConnectionManager(cm)
        .setDefaultCredentialsProvider(credentialsProvider)
        .setDefaultRequestConfig(requestConfig)
        .build();

在每个请求中使用相同的客户端实例:

Use the same client instance in every request:

            HttpPost httppost = new HttpPost(endPoint.trim());            
            // HttpClientContext is not thread safe, one per request must be created.
            HttpClientContext context = HttpClientContext.create();    
            response = this.httpclient.execute(httppost, context);

取消分配资源并将连接返回给连接管理器,在我的EJB的@PreDestroy方法中:

Deallocate the resources and return the connection back to connection manager, at the @PreDestroy method of my EJB:

             this.httpclient.close();

这篇关于在使用NTLM进行身份验证时,HttpClient 4.1.1返回401,浏览器工作正常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆