我尝试按照here
所述通过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;
}
答案 0 :(得分: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.
中所述答案 1 :(得分:2)
根据我的经验,覆盖BindingProvider参数不会设置所需的用户名和密码。证明这一点的最简单方法是无法通过BP覆盖传递域名。
我在互联网上看到过多个帖子,提示类似于Marcel Levy在上面建议使用NTLM身份验证器实例(根据Oracle提供的JAVA 6文档定义的方式)。但是,这个解决方案对我不起作用(我正在开发一个独立于任何应用程序服务器逻辑的独立程序)。
我用谷歌搜索并尝试了很多解决这个问题的方法..显然最简单的代码如下所示使用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 Instance的HTTP Client(我使用的是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();
答案 2 :(得分:1)
据我所知,您无法通过BindingProvider进行NTLM身份验证。
如果您熟悉Spring框架,则可以使用Spring-WS。 Spring-WS支持通过HttpComponentsMessageSender类与Apache HttpClient 4.x进行传输。 Apache HttpClient 4.x对NTLM身份验证有很好的支持。您可以使用wsimport工具生成的JAX-WS类作为marshalSendAndReceive的参数。