JAX-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身份validation。 可能是什么问题? 非常感谢!

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

在使用JAX-WS连接到Exchange Web服务时,我遇到了同样的问题,这对我有用:

首先,创建一个身份validation器:

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

在您的应用程序中,将身份validation器设置为默认值:

 String username = "DOMAIN\\USERNAME"; String password = "PASSWORD" NtlmAuthenticator authenticator = new NtlmAuthenticator(username, password); Authenticator.setDefault(authenticator); 

请注意,我正在使用方法#2来指定域,如Java文档中所述。

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

我在互联网上看过多篇post,提示类似于Marcel Levy在上面的建议,使用NTLM身份validation器实例(这是根据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


顺便说一句,如果你有一个需要传输的简单消息,只需使用NTCredentials实例的HTTP客户端(我使用4.3.4 …不确定早期版本)。 这也为我带来了魔力..样本如下:

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

据我所知,你不能通过BindingProvider进行NTLM身份validation。

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