【问题标题】:JAX-WS Sharepoint 401 Unauthorized NTLMJAX-WS Sharepoint 401 未经授权的 NTLM
【发布时间】:2011-06-19 09:45:49
【问题描述】:

我尝试通过 JAX-WS 访问 Sharepoint 列表,如 here 所述

但是,当运行下面的代码时,我得到:

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

【问题讨论】:

    标签: java sharepoint jax-ws exchange-server ntlm


    【解决方案1】:

    在将 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. 中所述

    【讨论】:

    • 这只是整个应用程序的设置吗?如果我只需要使用该凭据对特定请求进行身份验证怎么办?
    • 您可以通过自定义 Authenticator 类中的 getRequestingURL() 判断哪个 URL 正在请求凭据。因此,您可以相应地返回凭据。
    • @MarcelLevy - 您提供的代码在哪里适合 OP 问题中的代码?您提供的链接现已失效...
    • @Joe,很抱歉延迟了,但我已经更新了链接:docs.oracle.com/javase/6/docs/technotes/guides/net/…
    • @MarcelLevy 您的应用程序使用的是什么版本的 httpclient?还有什么jax-ws框架?我正在使用 httpclient 4.1.3 和 spring webservicetemplate 尝试此操作,但在部署到 Linux 机器时失败
    【解决方案2】:

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

    我在 Internet 上看到多篇帖子建议采用类似于上述 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) 的有效方法。请参考bughttps://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();
    

    【讨论】:

      【解决方案3】:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-15
        • 2012-05-17
        • 1970-01-01
        • 2017-02-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多