JAX-WS Sharepoint 401 未经授权的 NTLM

发布于 2024-10-15 22:42:20 字数 1233 浏览 6 评论 0原文

我尝试通过 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;
}

I try to access a Sharepoint list via JAX-WS as described here

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

孤单情人 2024-10-22 22:42:20

在使用 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 文档 中所述。

I was facing the same problem when connecting with JAX-WS to Exchange web services, and here's what worked for me:

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.

哎呦我呸! 2024-10-22 22:42:20

根据我的经验,覆盖 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 顺便说一句


,如果您有一个简单的消息需要传输,只需使用 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();

Based on my learnings, overriding the BindingProvider parameters does NOT set the required username and password. The simplest way to prove this is that there is no way to pass the domain name through the BP override.

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). 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

    //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. Please refer to bug 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. 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();
撩发小公举 2024-10-22 22:42:20

据我所知,您无法通过 BindingProvider 进行 NTLM 身份验证。

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

As far as I know, you can't do NTLM authentication through BindingProvider.

If you are familiar with Spring framework, you can use Spring-WS. Spring-WS supports transport with Apache HttpClient 4.x through the HttpComponentsMessageSender class. Apache HttpClient 4.x has good support for NTLM authentication. You can use the JAX-WS classes generated by wsimport tool as argument to marshalSendAndReceive.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文