Java 带有NTLM到SharePoint的CXF SOAP客户端

Java 带有NTLM到SharePoint的CXF SOAP客户端,java,sharepoint,soap,cxf,ntlm,Java,Sharepoint,Soap,Cxf,Ntlm,我正在为SharePoint 2007编写一个使用CXF框架(版本:2.7.8)的SOAP客户端。我遵循了添加NTLM支持的在线文档。我让客户端工作,跟踪HTTP会话显示正在发送NTLM凭据,但是,我仍然收到401未经授权的响应 代码: 有趣的是,我使用HTTP PUT for WebDAV编写了一个类似的客户端,以使用Apache HTTPClient库上载文档,并且能够使用NTLM成功地进行身份验证。此外,我还能够使用SOAPUI调用我正试图为其构建Java客户机的同一个Lists web服

我正在为SharePoint 2007编写一个使用CXF框架(版本:2.7.8)的SOAP客户端。我遵循了添加NTLM支持的在线文档。我让客户端工作,跟踪HTTP会话显示正在发送NTLM凭据,但是,我仍然收到401未经授权的响应

代码:

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

我假设CXF和HTTPClient之间NTLM的实现是不同的。关于我的CXF实现有什么问题吗?或者如何让它镜像HTTPClient实现?

请尝试这种方式

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 );
请往这边走

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

@拉马尔瓦诺,我也犯了这个错误。但我找到了另一种方法。您不需要将HttpConductor强制转换为AsynchttpConductor。让我们试试这些东西:

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);       
    }
}
公共类测试{
静态最终字符串kuser=“yourDomain\\username”;
静态最终字符串kpass=“yourPassword”;
静态类MyAuthenticator扩展了Authenticator{
公共密码身份验证getPasswordAuthentication(){
System.err.println(“输入“+getRequestingScheme()的用户名和密码”);
返回(新密码验证(kuser,kpass.tocharray());
}
}
公共静态void main(字符串[]args)引发异常{
setDefault(新的MyAuthenticator());
Lists listService=新列表();
ListsSoap端口=listService.getListsSoap();
Client Client=ClientProxy.getClient(端口);
httpconductor http=(httpconductor)client.getconductor();
HTTPClientPolicy HTTPClientPolicy=新的HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
字符串listName=“S030\u main”;
字符串rowLimit=“150”;
ArrayList listColumnNames=新建ArrayList();
listColumnNames.添加(“标题”);
Test.displaySharePointList(端口、listName、listColumnNames、rowLimit);
}
}
您可以在本文中找到displaySharePointList()方法的实现:


我希望这能保证你和其他人的安全。

@Lamarvanoy,我也犯了这个错误。但我找到了另一种方法。您不需要将HttpConductor强制转换为AsynchttpConductor。让我们试试这些东西:

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);       
    }
}
公共类测试{
静态最终字符串kuser=“yourDomain\\username”;
静态最终字符串kpass=“yourPassword”;
静态类MyAuthenticator扩展了Authenticator{
公共密码身份验证getPasswordAuthentication(){
System.err.println(“输入“+getRequestingScheme()的用户名和密码”);
返回(新密码验证(kuser,kpass.tocharray());
}
}
公共静态void main(字符串[]args)引发异常{
setDefault(新的MyAuthenticator());
Lists listService=新列表();
ListsSoap端口=listService.getListsSoap();
Client Client=ClientProxy.getClient(端口);
httpconductor http=(httpconductor)client.getconductor();
HTTPClientPolicy HTTPClientPolicy=新的HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
字符串listName=“S030\u main”;
字符串rowLimit=“150”;
ArrayList listColumnNames=新建ArrayList();
listColumnNames.添加(“标题”);
Test.displaySharePointList(端口、listName、listColumnNames、rowLimit);
}
}
您可以在本文中找到displaySharePointList()方法的实现:

我希望这能为你和其他人节省时间。

这对我来说很有效:

Client client = ClientProxy.getClient(port);
AsyncHTTPConduit conduit = (AsyncHTTPConduit)client.getConduit();
AuthorizationPolicy authorization = conduit.getAuthorization();
authorization.setUserName("domain\\username");
authorization.setPassword("password");
实际上,这对NTLM和Basic都有效

这对我有效:

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

实际上,这对NTLM和Basic都有效,这就是我要让我的工作正常所必须做的:

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

希望这可能会对某人有所帮助。

为了让我的工作顺利进行,我必须这样做:

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

希望这可能对某人有所帮助。

谢谢您的回复。当我尝试您的建议时,我得到:
org.apache.cxf.transport.http.urlconnectionhttpconductor不能强制转换为org.apache.cxf.transport.http.asyncclient.asynchtpconductor
。我正在使用
ClientProxy.getClient(proxy)
检索我的客户端。想法?为了使用org.apache.cxf.transport.http.asyncclient.asynchttpConductor代替org.apache.cxf.transport.http.urlconnectionHttpConductor,我们需要将cxf传输更改为cxf-rt-transports-http-hc-x.x.jar感谢您的响应。当我尝试您的建议时,我得到:
org.apache.cxf.transport.http.urlconnectionhttpconductor不能强制转换为org.apache.cxf.transport.http.asyncclient.asynchtpconductor
。我正在使用
ClientProxy.getClient(proxy)
检索我的客户端。想法?为了使用org.apache.cxf.transport.http.asyncclient.asynchtpconductor代替org.apache.cxf.transport.http.urlconnectionhttpconductor,我们需要将cxf transport更改为cxf-rt-transports-http-hc-x.x.jar