2011-02-01 41 views
13

tôi cố gắng truy cập vào một danh sách Sharepoint qua JAX-WS như mô tả hereJAX-WS Sharepoint 401 NTLM trái phép

Tuy nhiên, khi chạy đoạn code dưới đây tôi nhận được:

java.lang.Exception: Exception. See stacktrace.com.sun.xml.internal.ws.client.ClientTransportException: The server sent HTTP status code 401: Unauthorized 

Sharepoint yêu cầu xác thực NTLM. Điều gì có thể là vấn đề? Cảm ơn rất nhiều!

public static ListsSoap sharePointListsAuth(String userName, String password) throws Exception { 
    ListsSoap port = null; 
    if (userName != null && password != null) { 
     try { 
      Lists service = new Lists(); 
      port = service.getListsSoap(); 
      System.out.println("Web Service Auth Username: " + userName); 
      ((BindingProvider) port).getRequestContext().put(BindingProvider.USERNAME_PROPERTY, userName); 
      ((BindingProvider) port).getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, password); 
     } catch (Exception e) { 
      throw new Exception("Error: " + e.toString()); 
     } 
    } else { 
     throw new Exception("Couldn't authenticate: Invalid connection details given."); 
    } 
    return port; 
} 

Trả lời

17

tôi đã phải đối mặt với cùng một vấn đề khi kết nối với JAX-WS với các dịch vụ web của Exchange, và đây là những gì làm việc cho tôi:

Đầu tiên, tạo một xác thực:

import java.net.Authenticator; 
import java.net.PasswordAuthentication; 

public class NtlmAuthenticator extends Authenticator { 

    private final String username; 
    private final char[] password; 

    public NtlmAuthenticator(final String username, final String password) { 
    super(); 
    this.username = new String(username); 
    this.password = password.toCharArray(); 
    } 

    @Override 
    public PasswordAuthentication getPasswordAuthentication() { 
    return (new PasswordAuthentication (username, password)); 
    } 
} 

Trong của bạn ứng dụng, thiết lập trình xác thực làm mặc định:

String username = "DOMAIN\\USERNAME"; 
String password = "PASSWORD" 

NtlmAuthenticator authenticator = new NtlmAuthenticator(username, password); 
Authenticator.setDefault(authenticator); 

Lưu ý rằng tôi đang sử dụng phương pháp # 2 để chỉ định miền như được mô tả trong Java documentation.

+0

Đó có phải là thiết lập duy nhất cho toàn bộ ứng dụng không? Điều gì sẽ xảy ra nếu tôi cần xác thực yêu cầu cụ thể với thông tin đăng nhập đó? – glaz666

+0

Bạn có thể biết URL nào đang yêu cầu thông tin đăng nhập bằng getRequestingURL() bên trong lớp Authenticator tùy chỉnh của bạn. Vì vậy, bạn có thể trả lại thông tin xác thực cho phù hợp. – jmend

+0

@MarcelLevy - Mã bạn cung cấp ở đâu phù hợp với mã trong câu hỏi của OP? Liên kết bạn cung cấp hiện đã chết ... – Joe

1

Theo như tôi biết, bạn không thể thực hiện xác thực NTLM thông qua BindingProvider.

Nếu bạn đã quen thuộc với khung công tác Spring, bạn có thể sử dụng Spring-WS. Spring-WS hỗ trợ truyền tải với Apache HttpClient 4.x thông qua lớp HttpComponentsMessageSender. Apache HttpClient 4.x có hỗ trợ tốt cho xác thực NTLM. Bạn có thể sử dụng các lớp JAX-WS được tạo bởi công cụ wsimport làm đối số cho marshalSendAndReceive.

2

Dựa trên các bài học của tôi, việc ghi đè tham số BindingProvider KHÔNG đặt tên người dùng và mật khẩu yêu cầu. Cách đơn giản nhất để chứng minh điều này là không có cách nào để chuyển tên miền thông qua ghi đè BP.

Tôi đã xem nhiều bài đăng qua internet đề xuất một cách tương tự như đề xuất của Marcel Levy ở trên để sử dụng cá thể xác thực NTLM (Đó là cách được xác định theo tài liệu JAVA 6 có sẵn từ Oracle). Tuy nhiên, giải pháp này không làm việc cho tôi (tôi đã phát triển một chương trình độc lập độc lập với bất kỳ logic máy chủ ứng dụng nào).

Tôi googled và cố gắng rất nhiều giải pháp cho vấn đề này .. hình như mã đơn giản nhất mà làm việc như sau sử dụng thư viện JCIFS

//Set the jcifs properties 
    jcifs.Config.setProperty("jcifs.smb.client.domain", "domainname"); 
    jcifs.Config.setProperty("jcifs.netbios.wins", "xxx.xxx.xxx.xxx"); 
    jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "300000"); // 5 minutes 
    jcifs.Config.setProperty("jcifs.netbios.cachePolicy", "1200"); // 20 minutes 
    jcifs.Config.setProperty("jcifs.smb.client.username", "username"); 
    jcifs.Config.setProperty("jcifs.smb.client.password", "password"); 

    //Register the jcifs URL handler to enable NTLM 
    jcifs.Config.registerSmbURLHandler(); 

Rõ ràng CXF 3,0 doesnt có một cách hợp lệ của cấu hình HTTP Client (4.3.x) với cá thể NTCredentials. Vui lòng tham khảo lỗi https://issues.apache.org/jira/browse/CXF-5671


Bằng cách này, nếu bạn có một thông điệp đơn giản mà cần phải được truyền đi, chỉ cần sử dụng HTTP Client (Tôi làm việc sử dụng 4.3.4 .. không chắc chắn về các phiên bản trước đó) với NTCredentials Ví dụ. Điều đó cũng đã làm phép thuật cho tôi .. Mẫu như sau:

final NTCredentials ntCredentials = new NTCredentials("username", "Passworrd","destination", "domain"); 
    CredentialsProvider credsProvider = new BasicCredentialsProvider(); 

    credsProvider.setCredentials(AuthScope.ANY, ntCredentials); 
    CloseableHttpClient httpclient = HttpClientBuilder.create() 
             .setDefaultCredentialsProvider(credsProvider) 
             .build(); 
Các vấn đề liên quan