【问题标题】:CXF SOAP Client with NTLM to SharePointCXF SOAP 客户端与 NTLM 到 SharePoint
【发布时间】:2014-02-12 20:42:12
【问题描述】:

我正在为 SharePoint 2007 编写使用 CXF 框架(版本:2.7.8)的 SOAP 客户端。我已按照在线文档添加 NTLM 支持here。我让客户端工作并跟踪 HTTP 会话显示正在发送 NTLM 凭据,但是,我仍然收到 401 Unauthorized 响应。

代码:

Lists listService = new Lists();
ListsSoap port = listService.getListsSoap();

BindingProvider bp = (BindingProvider) port;
bp.getRequestContext().put("use.async.http.conduit", Boolean.TRUE);
Credentials creds = new NTCredentials(USER, PASS, "", DOMAIN);
bp.getRequestContext().put(Credentials.class.getName(), creds);

Client client = ClientProxy.getClient(proxy);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
httpClientPolicy.setAutoRedirect(true);
http.setClient(httpClientPolicy);

// Build request and execute

有趣的是,我使用 HTTP PUT for WebDAV 编写了一个类似的客户端,以使用 Apache HTTPClient 库上传文档,并且能够使用 NTLM 成功进行身份验证。此外,我能够使用 SOAPUI 调用我尝试为其构建 Java 客户端的相同 Lists Web 服务,并且它也使用 NTLM 成功进行了身份验证。

我假设 NTLM 的实现在 CXF 和 HTTPClient 之间是不同的。关于我的 CXF 实施有什么问题有什么想法吗?或者我怎样才能让它镜像 HTTPClient 实现?

【问题讨论】:

    标签: java sharepoint soap cxf ntlm


    【解决方案1】:

    请试试这个方法!

    HTTPConduit http = (HTTPConduit)client.getConduit();
    AsyncHTTPConduit conduit = (AsyncHTTPConduit)http;
    DefaultHttpAsyncClient defaultHttpAsyncClient;
    defaultHttpAsyncClient = conduit.getHttpAsyncClient();
    defaultHttpAsyncClient.getCredentialsProvider().setCredentials( AuthScope.ANY,
     new NTCredentials( USER,PWD, "", DOM ) );
    conduit.getClient().setAllowChunking( false );
    conduit.getClient().setAutoRedirect( true );
    

    【讨论】:

    • 感谢您的回复。当我尝试您的建议时,我得到:org.apache.cxf.transport.http.URLConnectionHTTPConduit cannot be cast to org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit。我正在使用ClientProxy.getClient(proxy) 检索我的客户。想法?
    • 为了使用 org.apache.cxf.transport.http.asyncclient.AsyncHTTPConduit 插入 org.apache.cxf.transport.http.URLConnectionHTTPConduit 我们需要将 CXF trannsport 更改为 cxf-rt-transports -http-hc-x.x.x.jar
    【解决方案2】:

    @lamarvannoy,我也遇到了这个错误。但我找到了另一种方法。您不需要将 HTTPConduit 转换为 AsyncHTTPConduit。让我们试试这个东西:

    public class Test {
    
        static final String kuser = "yourDomain\\username";
        static final String kpass = "yourPassword";
    
        static class MyAuthenticator extends Authenticator {
            public PasswordAuthentication getPasswordAuthentication() {
                System.err.println("Feeding username and password for " + getRequestingScheme());
                return (new PasswordAuthentication(kuser, kpass.toCharArray()));
            }
        }
    
        public static void main(String[] args) throws Exception {
            Authenticator.setDefault(new MyAuthenticator());
            Lists listService = new Lists();
            ListsSoap port = listService.getListsSoap();
    
            Client client = ClientProxy.getClient(port);
            HTTPConduit http = (HTTPConduit) client.getConduit();
            HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
            httpClientPolicy.setConnectionTimeout(36000);
            httpClientPolicy.setAllowChunking(false);
            http.setClient(httpClientPolicy);
    
            String listName = "S030_main";
            String rowLimit = "150";
            ArrayList<String> listColumnNames = new ArrayList<String>();
            listColumnNames.add("Title");     
            Test.displaySharePointList(port, listName, listColumnNames, rowLimit);       
        }
    }
    

    您可以在这篇文章中找到 displaySharePointList() 方法的实现:http://davidsit.wordpress.com/2010/02/10/reading-a-sharepoint-list-with-java-tutorial/

    我希望这会保护您和其他人的时间。

    【讨论】:

      【解决方案3】:

      这对我有用:

      Client client = ClientProxy.getClient(port);
      AsyncHTTPConduit conduit = (AsyncHTTPConduit)client.getConduit();
      AuthorizationPolicy authorization = conduit.getAuthorization();
      authorization.setUserName("domain\\username");
      authorization.setPassword("password");
      

      实际上这对 NTLM 和 Basic 都有效

      【讨论】:

        【解决方案4】:

        这是我必须做的才能让我的工作:

        // Include a version of WSDL in class path, make URL point to that
        URL url = MyClient.class.getResource("previouslydownloaded.wsdl");
        
        MyCxFService ws = new MyCxFService(url);
        MyCxfClient client = ws.getMyCxfServicePort(); 
        
        BindingProvider prov = ((BindingProvider) client);
        Binding binding = prov.getBinding();
        
        // Set Username and Password
        if ((this.user != null) && (!this.user.isEmpty())) {
          prov.getRequestContext().put(BindingProvider.USERNAME_PROPERTY, this.user);
          prov.getRequestContext().put(BindingProvider.PASSWORD_PROPERTY, this.passwd);
        }
        
        // Get address from config file to get rid error caused by using wsdl file:
        // Caused by: java.lang.NullPointerException
        //   at org.apache.cxf.transport.http.URLConnectionHTTPConduit.createConnection(URLConnectionHTTPConduit.java:104)
        prov.getRequestContext().put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, this.portAddress);
        

        希望对某人有所帮助。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多