我在使用 Apache CFX 调用 SOAP Web 服务并与我们的公司 NTLM 代理进行身份验证时遇到了一些麻烦。我必须使用JCFS,因为我们的安装程序使用 Java 5。应用程序服务器是 Glassfish 2.1.1。
public Client() {
final String username = USERNAME;
final String password = PASSWORD;
final String url = CONNECTION_URL;
final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
logger.debug("JaxWSProxy Factory created");
// Basic authentication
factory.setUsername(username);
logger.debug("Set SOAP username");
factory.setPassword(password);
logger.debug("Set SOAP password");
final GZIPInInterceptor gzipInterceptor = new GZIPInInterceptor();
factory.getInInterceptors().add(gzipInterceptor);
final FIStaxInInterceptor fastInfoSetIn = new FIStaxInInterceptor();
factory.getInInterceptors().add(fastInfoSetIn);
final FIStaxOutInterceptor fastInfoSetOut = new FIStaxOutInterceptor();
factory.getOutInterceptors().add(fastInfoSetOut);
logger.debug("Interceptors initialized");
// Configure WS-Security Header
// Connnection to SOAP endpoint - only possible with security header
Map properties = new HashMap();
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(properties);
factory.getOutInterceptors().add(wssOut);
factory.getOutInterceptors().add(new SAAJOutInterceptor());
properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP);
// Specify username
properties.put(WSHandlerConstants.USER, username);
// Password type :plain text
properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
// Callback used to retrieve password for given user
properties.put(WSHandlerConstants.PW_CALLBACK_REF, new ClientPasswordHandler(password));
// Set interface class
factory.setServiceClass(FeedInterface.class);
// Set url
factory.setAddress(url);
this.Feed = (FeedInterface) factory.create();
//Set the jcifs properties
jcifs.Config.setProperty("jcifs.smb.client.domain", "domain");
jcifs.Config.setProperty("jcifs.netbios.wins", "xxx.xxx.xxx.xx");
jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "300000");
jcifs.Config.setProperty("jcifs.netbios.cachePolicy", "1200");
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();
//Turn off chunking so that NTLM can occur
Client client = ClientProxy.getClient(this.Feed);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(36000);
httpClientPolicy.setAllowChunking(false);
http.setClient(httpClientPolicy);
logger.debug("Client created");
}
/**
* Gets the Service web service client. <p>
* <p/>
* @return Returns the feed.
*/
public FeedInterface getfeed() {
return Feed;
}
/**
* Private class to handle setting the client password on the WS-Security envelope.
*/
class ClientPasswordHandler implements CallbackHandler {
private String password = null;
public ClientPasswordHandler(String password) {
this.password = password;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
// set the password for the outbound message.
pc.setPassword(this.password);
}
}
}
我也测试了这个解决方案:
public Client() {
final String username = USERNAME;
final String password = PASSWORD;
final String url = CONNECTION_URL;
final JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
logger.debug("JaxWSProxy Factory created");
// Basic authentication
factory.setUsername(username);
logger.debug("Set SOAP username");
factory.setPassword(password);
logger.debug("Set SOAP password");
final GZIPInInterceptor gzipInterceptor = new GZIPInInterceptor();
factory.getInInterceptors().add(gzipInterceptor);
final FIStaxInInterceptor fastInfoSetIn = new FIStaxInInterceptor();
factory.getInInterceptors().add(fastInfoSetIn);
final FIStaxOutInterceptor fastInfoSetOut = new FIStaxOutInterceptor();
factory.getOutInterceptors().add(fastInfoSetOut);
logger.debug("Interceptors initialized");
// Configure WS-Security Header
// Connnection to SOAP endpoint - only possible with security header
Map properties = new HashMap();
WSS4JOutInterceptor wssOut = new WSS4JOutInterceptor(properties);
factory.getOutInterceptors().add(wssOut);
factory.getOutInterceptors().add(new SAAJOutInterceptor());
properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.USERNAME_TOKEN + " " + WSHandlerConstants.TIMESTAMP);
// Specify username
properties.put(WSHandlerConstants.USER, username);
// Password type :plain text
properties.put(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
// Callback used to retrieve password for given user
properties.put(WSHandlerConstants.PW_CALLBACK_REF, new ClientPasswordHandler(password));
// Set interface class
factory.setServiceClass(FeedInterface.class);
// Set url
factory.setAddress(url);
final String authUser = "username";
final String authPassword = "password";
Authenticator.setDefault(new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(authUser, authPassword.toCharArray());
}
});
System.setProperty("http.proxySet", "true");
System.setProperty("https.proxyHost", "xxxx.xxxx");
System.setProperty("https.proxyPort", "8080");
this.Feed = (FeedInterface) factory.create();
logger.debug("Client created");
}
/**
* Gets the Service web service client. <p>
* <p/>
* @return Returns the feed.
*/
public FeedInterface getfeed() {
return Feed;
}
/**
* Private class to handle setting the client password on the WS-Security envelope.
*/
class ClientPasswordHandler implements CallbackHandler {
private String password = null;
public ClientPasswordHandler(String password) {
this.password = password;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
// set the password for the outbound message.
pc.setPassword(this.password);
}
}
}
我总是收到此连接被拒绝异常:
2013-04-23 16:52:34 SessionCron [ERROR] Exception encountered running SessionCron. For stack trace see debug log.
2013-04-23 16:52:34 SessionCron [DEBUG] Stack trace:
javax.xml.ws.soap.SOAPFaultException: Connection refused
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:156)
at com.sun.proxy.$Proxy103.getXXXX(Unknown Source)
at xxx.yyyyyy..SessionAgent.updateXXXXData(SessionAgent.java:260)
at xxx.yyyyyy..SessionAgent.checkForUpdates(SessionAgent.java:143)
at xxx.yyyyyy.util.SessionCron.run(SessionCron.java:40)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRunAndReset(FutureTask.java:317)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:150)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:98)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.runPeriodic(ScheduledThreadPoolExecutor.java:180)
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:204)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:680)
Caused by: com.sun.xml.stream.XMLStreamException2
at com.sun.xml.stream.writers.XMLStreamWriterImpl.writeStartElement(XMLStreamWriterImpl.java:1363)
at org.apache.cxf.staxutils.StaxUtils.writeStartElement(StaxUtils.java:586)
at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:525)
at org.apache.cxf.staxutils.StaxUtils.copy(StaxUtils.java:513)
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:210)
at org.apache.cxf.binding.soap.saaj.SAAJOutInterceptor$SAAJOutEndingInterceptor.handleMessage(SAAJOutInterceptor.java:171)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:535)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:465)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:368)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:321)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:88)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:134)
... 13 more
Caused by: java.net.ConnectException: Connection refused
at java.net.PlainSocketImpl.socketConnect(Native Method)
at java.net.PlainSocketImpl.doConnect(PlainSocketImpl.java:351)
at java.net.PlainSocketImpl.connectToAddress(PlainSocketImpl.java:213)
at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:200)
at java.net.Socket.connect(Socket.java:529)
at sun.net.NetworkClient.doConnect(NetworkClient.java:158)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:388)
at sun.net.www.http.HttpClient$3.run(HttpClient.java:451)
at java.security.AccessController.doPrivileged(Native Method)
at sun.net.www.http.HttpClient.privilegedOpenServer(HttpClient.java:433)
at sun.net.www.http.HttpClient.openServer(HttpClient.java:514)
at sun.net.www.protocol.https.HttpsClient.<init>(HttpsClient.java:272)
at sun.net.www.protocol.https.HttpsClient.New(HttpsClient.java:329)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.getNewHttpClient(AbstractDelegateHttpsURLConnection.java:172)
at sun.net.www.protocol.http.HttpURLConnection.plainConnect(HttpURLConnection.java:949)
at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:158)
at sun.net.www.protocol.http.HttpURLConnection.getOutputStream(HttpURLConnection.java:1014)
at sun.net.www.protocol.https.HttpsURLConnectionImpl.getOutputStream(HttpsURLConnectionImpl.java:230)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleHeadersTrustCaching(HTTPConduit.java:1368)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.onFirstWrite(HTTPConduit.java:1310)
at org.apache.cxf.io.AbstractWrappedOutputStream.write(AbstractWrappedOutputStream.java:42)
at org.apache.cxf.io.AbstractThresholdOutputStream.unBuffer(AbstractThresholdOutputStream.java:89)
at org.apache.cxf.io.AbstractThresholdOutputStream.write(AbstractThresholdOutputStream.java:79)
at com.sun.xml.stream.writers.UTF8OutputStreamWriter.write(UTF8OutputStreamWriter.java:107)
at com.sun.xml.stream.writers.XMLStreamWriterImpl.openStartTag(XMLStreamWriterImpl.java:1588)
at com.sun.xml.stream.writers.XMLStreamWriterImpl.writeStartElement(XMLStreamWriterImpl.java:1322)
... 25 more