2011-02-01 115 views
13

我试着描述hereJAX-WS的Sharepoint 401未授权NTLM

通过JAX-WS访问SharePoint列表但是,当运行代码时下面我得到:

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

的Sharepoint需要NTLM身份验证。可能是什么问题?非常感谢!

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

回答

17

与JAX-WS连接到Exchange Web服务时,我面临同样的问题,这里是为我工作:

首先,创建一个认证:

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

在你应用程序,设置认证为默认:

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

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

请注意,我使用的方法#2如Java documentation.

+0

难道只有整个应用程序的设置?如果我需要使用该凭据对特定请求进行身份验证,该怎么办? – glaz666 2011-07-07 12:27:35

1

中所述的指定域据我所知,您不能通过BindingProvider进行NTLM身份验证。

如果您熟悉Spring框架,可以使用Spring-WS。 Spring-WS支持使用Apache HttpClient 4.x通过HttpComponentsMessageSender类进行传输。 Apache HttpClient 4.x对NTLM身份验证有很好的支持。您可以使用由wsimport工具生成的JAX-WS类作为marshalSendAndReceive的参数。

2

根据我的学习,重写BindingProvider参数不会设置所需的用户名和密码。证明这一点最简单的方法是,没有办法通过BP覆盖来传递域名。

我已经在互联网上看到多个帖子,建议类似于Marcel Levy的建议,使用NTLM authenticator实例(这是根据Oracle提供的JAVA 6文档定义的方式)。但是,这个解决方案并不适合我(我正在开发独立于任何应用程序服务器逻辑的独立程序)。

我用Google搜索,并尝试了很多解决方案,这个问题..显然是因为工作的最简单的代码如下使用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(); 

显然CXF 3.0不必须配置的有效途径具有NTCredentials实例的HTTP客户端(4.3.x)。请参考错误https://issues.apache.org/jira/browse/CXF-5671


顺便说一句,如果你有一个简单的信息需要被传输,只需使用HTTP客户端(我曾使用4.3.4 ..不知道的更早版本的)与NTCredentials实例。这对我来说也是如此。示例如下:

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