2011-05-06 30 views
8

Tôi đang cố gắng sử dụng Apache/Jakarta HttpClient 4.1.1 để kết nối với một trang web tùy ý bằng các thông tin xác thực đã cho. Để kiểm tra điều này, tôi có một cài đặt tối thiểu của IIS 7.5 trên máy dev của tôi đang chạy, nơi chỉ có một chế độ xác thực được kích hoạt tại một thời điểm. Xác thực cơ bản hoạt động tốt, nhưng Digest và NTLM trở lại 401 thông báo lỗi bất cứ khi nào tôi cố gắng đăng nhập Đây là mã của tôi:.HttpClient 4.1.1 trả về 401 khi xác thực với NTLM, các trình duyệt hoạt động tốt

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

Một trong những điều tôi đã nhận thấy trong Fiddler là băm gửi bởi Firefox so với bằng HttpClient là khác nhau, làm cho tôi nghĩ rằng có lẽ IIS 7,5 đang mong đợi băm mạnh hơn HttpClient cung cấp? Bất kỳ ý tưởng? Nó sẽ là tuyệt vời nếu tôi có thể xác minh rằng điều này sẽ làm việc với NTLM. Tiêu hóa cũng sẽ tốt đẹp, nhưng tôi có thể sống mà không có điều đó nếu cần thiết.

+0

Tôi nhận được xác thực Digest để hoạt động trong trình duyệt, nhưng nó vẫn hiển thị 401 bị cấm trong HttpClient. Tôi bối rối. – Jesse

+0

Mã hoạt động đối với tôi, tuy nhiên mã này không còn được dùng nữa trong 4.3. Tôi không thể tìm thấy hướng dẫn rõ ràng để sử dụng mã 4.3 thuần túy. – Paul

Trả lời

7

Tôi không phải là một chuyên gia về đề tài này nhưng trong quá trình xác thực NTLM sử dụng các thành phần http Tôi đã thấy rằng khách hàng cần 3 cố gắng để kết nối với một thiết bị đầu cuối NTML trong trường hợp của tôi. Đó là kinda mô tả here cho Spnego nhưng nó là một chút khác nhau cho việc xác thực NTLM.

Đối với NTLM trong client nỗ lực đầu tiên sẽ thực hiện một yêu cầu với Target auth state: UNCHALLENGED và Web server trả về HTTP 401 tình trạng và một tiêu đề: WWW-Authenticate: NTLM

Khách hàng sẽ kiểm tra các đề án xác thực cấu hình, NTLM nên được cấu hình trong mã khách hàng.

nỗ lực Thứ hai, khách hàng sẽ thực hiện một yêu cầu với Target auth state: CHALLENGED, và sẽ gửi một tiêu đề uỷ quyền với một mã thông báo được mã hóa dưới dạng base64: Authorization: NTLM TlRMTVNTUAABAAAAAYIIogAAAAAoAAAAAAAAACgAAAAFASgKAAAADw== máy chủ một lần nữa trả về HTTP 401 status nhưng tiêu đề: WWW-Authenticate: NTLM hiện lưu trữ những thông tin được mã hóa.

Nỗ lực thứ 3 Khách hàng sẽ sử dụng thông tin từ tiêu đề WWW-Authenticate: NTLM và sẽ thực hiện yêu cầu cuối cùng với Target auth state: HANDSHAKE và tiêu đề ủy quyền Authorization: NTLM có chứa thêm thông tin cho máy chủ.

Trong trường hợp của tôi, tôi nhận được HTTP/1.1 200 OK sau đó.

Để tránh tất cả điều này trong mọi yêu cầu documentation tại chương 4.7.1 nêu rõ rằng mã thông báo thực thi giống nhau phải được sử dụng cho các yêu cầu liên quan đến logic. Đối với tôi nó đã không hoạt động.

Mã của tôi: tôi khởi tạo cho khách hàng một lần trong một phương pháp @PostConstruct của một 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(); 

Sử dụng các ví dụ cùng một khách hàng trong mọi yêu cầu:

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

deallocate các nguồn lực và trả lại kết nối quay lại trình quản lý kết nối, theo phương pháp @PreDestroy của EJB của tôi:

   this.httpclient.close(); 
2

Cách dễ nhất khắc phục sự cố các tình huống như vậy mà tôi đã tìm thấy là Wireshark. Nó là một cái búa rất lớn, nhưng nó thực sự sẽ cho bạn thấy mọi thứ. Cài đặt nó, đảm bảo máy chủ của bạn nằm trên một máy khác (không hoạt động với Localhost) và bắt đầu ghi nhật ký.

Chạy yêu cầu của bạn không thành công, chạy yêu cầu hoạt động. Sau đó, lọc theo http (chỉ cần đặt http trong trường bộ lọc), tìm yêu cầu GET đầu tiên, tìm yêu cầu GET khác và so sánh. Xác định sự khác biệt có ý nghĩa, bây giờ bạn có từ khóa hoặc vấn đề cụ thể để tìm kiếm mã/net cho. Nếu không đủ, hãy thu hẹp cuộc hội thoại TCP đầu tiên và xem xét toàn bộ yêu cầu/phản hồi. Tương tự với cái còn lại.

Tôi đã giải quyết được một số vấn đề không thể tin được với cách tiếp cận đó. Và Wireshark là công cụ rất hữu ích để biết. Rất nhiều chức năng siêu tiên tiến để làm cho mạng của bạn gỡ lỗi dễ dàng hơn.

Bạn cũng có thể chạy nó trên một trong hai máy khách hoặc máy chủ kết thúc. Bất cứ điều gì sẽ cho bạn thấy cả hai yêu cầu để cho phép bạn so sánh.

1

Cuối cùng tôi đã tìm ra. Xác thực thông báo yêu cầu rằng nếu bạn sử dụng URL đầy đủ trong yêu cầu, proxy cũng cần phải sử dụng URL đầy đủ. Tôi đã không để lại mã proxy trong mẫu, nhưng nó đã được chuyển hướng đến "localhost", điều này làm cho nó thất bại. Thay đổi điều này thành 127.0.0.1 làm cho nó hoạt động.

3

Tôi gặp sự cố tương tự với HttpClient 4.1.2. Đối với tôi, nó đã được giải quyết bằng cách hoàn nguyên về HttpClient 4.0.3. Tôi không bao giờ có thể nhận được NTLM làm việc với 4.1.2 bằng cách sử dụng hoặc cài đặt sẵn hoặc sử dụng JCIFS.

+0

Chỉ cần một lưu ý, tôi cũng gặp phải vấn đề này. Bản phát hành http.3ient 4.2.3 tuyên bố có một triển khai NTLM được làm mới. Tôi thấy rằng việc nâng cấp lên 4.2.3 hoạt động hoàn hảo liên quan đến NTLM. –

4

Tôi đã gặp phải sự cố tương tự với HttpClient4.1.X Sau khi nâng cấp lên HttpClient 4.2.6 nó đã hấp dẫn như sự quyến rũ. Dưới đây là mã của tôi

DefaultHttpClient httpclient = new DefaultHttpClient(); 
     HttpContext localContext = new BasicHttpContext(); 
     HttpGet httpget = new HttpGet("url"); 
     CredentialsProvider credsProvider = new BasicCredentialsProvider(); 
     credsProvider.setCredentials(AuthScope.ANY, 
       new NTCredentials("username", "pwd", "", "domain")); 
        List<String> authtypes = new ArrayList<String>(); 
      authtypes.add(AuthPolicy.NTLM);  
      httpclient.getParams().setParameter(AuthPNames.TARGET_AUTH_PREF,authtypes); 

     localContext.setAttribute(ClientContext.CREDS_PROVIDER, credsProvider); 
     HttpResponse response = httpclient.execute(httpget, localContext); 
     HttpEntity entity=response.getEntity(); 
+0

Mã này làm việc cho tôi với phiên bản 4.2.2 ... Chúc mừng! –

2

Cập nhật ứng dụng của chúng tôi để sử dụng các lọ trong httpcomponents-client-4.5.1 đã giải quyết vấn đề này cho tôi.

Các vấn đề liên quan