简体   繁体   English

JAX-WS Sharepoint 401未经授权的NTLM

[英]JAX-WS Sharepoint 401 Unauthorized NTLM

I try to access a Sharepoint list via JAX-WS as described here 我试着通过JAX-WS访问SharePoint列表中所描述的在这里

However, when running the code below I get: 但是,当运行下面的代码时,我得到:

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

Sharepoint requires NTLM authentication. Sharepoint需要NTLM身份验证。 What may be the problem? 可能是什么问题? Thanks a lot! 非常感谢!

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

I was facing the same problem when connecting with JAX-WS to Exchange web services, and here's what worked for me: 在使用JAX-WS连接到Exchange Web服务时,我遇到了同样的问题,这对我有用:

First, create an authenticator: 首先,创建一个身份验证器:

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

In your application, set up the authenticator as the default: 在您的应用程序中,将身份验证器设置为默认值:

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

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

Note that I'm using method #2 for specifying the domain as described in the Java documentation. 请注意,我正在使用方法#2来指定域,如Java文档中所述。

Based on my learnings, overriding the BindingProvider parameters does NOT set the required username and password. 根据我的学习,覆盖BindingProvider参数不会设置所需的用户名和密码。 The simplest way to prove this is that there is no way to pass the domain name through the BP override. 证明这一点的最简单方法是无法通过BP覆盖传递域名。

I've seen multiple posts over the internet suggesting a way similar to Marcel Levy's suggestion in above to use an NTLM authenticator instance (Which is the way defined as per JAVA 6 documentation available from Oracle). 我在互联网上看过多篇帖子,提示类似于Marcel Levy在上面的建议,使用NTLM身份验证器实例(这是根据Oracle提供的JAVA 6文档定义的方式)。 But, this solution did not work for me (I was developing a standalone program independent of any application server logic). 但是,这个解决方案对我不起作用(我正在开发一个独立于任何应用程序服务器逻辑的独立程序)。

I googled and tried a lot of solutions to this problem.. apparently the simplest code that worked is as below using the JCIFS library 我用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();

Apparently CXF 3.0 doesnt have a valid way of configuring the HTTP Client (4.3.x) with NTCredentials instance. 显然,CXF 3.0没有一种使用NTCredentials实例配置HTTP客户端(4.3.x)的有效方法。 Please refer to bug https://issues.apache.org/jira/browse/CXF-5671 请参阅错误https://issues.apache.org/jira/browse/CXF-5671


By the way, if you have a simple message which needs to be transmitted, just use HTTP Client (I worked using 4.3.4.. not sure of the earlier versions) with NTCredentials Instance. 顺便说一句,如果你有一个需要传输的简单消息,只需使用NTCredentials实例的HTTP客户端(我使用4.3.4 ...不确定早期版本)。 That too did the magic for me.. The sample is as below: 这也为我带来了魔力..样本如下:

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

As far as I know, you can't do NTLM authentication through BindingProvider. 据我所知,你不能通过BindingProvider进行NTLM身份验证。

If you are familiar with Spring framework, you can use Spring-WS . 如果您熟悉Spring框架,则可以使用Spring-WS Spring-WS supports transport with Apache HttpClient 4.x through the HttpComponentsMessageSender class. Spring-WS支持通过HttpComponentsMessageSender类与Apache HttpClient 4.x进行传输。 Apache HttpClient 4.x has good support for NTLM authentication. Apache HttpClient 4.x对NTLM身份验证有很好的支持。 You can use the JAX-WS classes generated by wsimport tool as argument to marshalSendAndReceive . 您可以使用wsimport工具生成的JAX-WS类作为marshalSendAndReceive的参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM