我遇到了同样的问题,最后我们使用 Apache CXF 库来创建客户端并为它编写了一些拦截器。在我们的例子中,Web 服务具有身份验证标头,并且启用了 X509。以下代码对我有用,我与您分享:-
要离线生成 Web 服务客户端,您可以将 wsdl 的 xml 保存在本地机器中,然后使用 wsconsume/wsdl2java 命令创建存根。
在下面的代码中,如果 SOAP Header 中没有为 Web 服务设置用户名和密码,则可以跳过 addSoapHeader 部分。
TestClient.java:-
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.Authenticator;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.xml.bind.JAXBException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
import javax.xml.namespace.QName;
import javax.xml.ws.soap.AddressingFeature;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.headers.Header;
import org.apache.cxf.jaxb.JAXBDataBinding;
import org.apache.cxf.ws.addressing.AddressingProperties;
import org.apache.cxf.ws.addressing.AttributedURIType;
import org.apache.cxf.ws.addressing.EndpointReferenceType;
import org.apache.cxf.ws.addressing.VersionTransformer;
import org.apache.cxf.ws.addressing.impl.AddressingPropertiesImpl;
import org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor;
import org.apache.ws.security.handler.WSHandlerConstants;
import com.icbase.tsamplex509.ArrayOfDetailLineItem;
import com.icbase.tsamplex509.ArrayOfInventoryLineItem;
import com.icbase.tsamplex509.AuthHeader;
import com.icbase.tsamplex509.CompleteInventory;
import com.icbase.tsamplex509.DetailLineItem;
import com.icbase.tsamplex509.InventoryLineItem;
import com.icbase.tsamplex509.OrderAdd;
import com.icbase.tsamplex509.OrderStatus;
import com.icbase.tsamplex509.ResultMessage;
import com.icbase.tsamplex509.Service;
import com.icbase.tsamplex509.ServiceSoap;
import com.st.passport.PassportWebServiceHandler;
import com.st.passport.UserInfo;
import com.sun.org.apache.xerces.internal.jaxp.datatype.XMLGregorianCalendarImpl;
public class TestClient
{
private static String proxyUser = "javaMagician";
private static String proxyPassword = "myProxyPws";
private static String proxyHost = "sxf4.dlh.ts.com";
private static String proxyPort = "8080";
private static String wsURL = "http://www.wsdoamin.com/tssamplex509/service.asmx?WSDL";
public static void main(String[] args) throws MalformedURLException, Exception
{
Authenticator.setDefault(new ANSAuthenticationHandler(proxyUser,proxyPassword));
System.getProperties().put("http.proxyHost", proxyHost);
System.getProperties().put("http.proxyPort", proxyPort);
Service service = new Service(new URL(wsURL),new QName("http://www.wsdoamin.com/tssamplex509/", "Service"));
ServiceSoap port = service.getServiceSoap(new AddressingFeature(true,true));
Client client = ClientProxy.getClient(port);
enableWSAddressing(client);
enableWsSecurity(client);
addSOAPHeader(client);
System.out.println("Invoking Web Service ...");
//Calling First Web service
CompleteInventory getProductResponse = port.getproduct("*");
System.out.println("Result :: " + getProductResponse.getResultMessage().getResult().name());
System.out.println("Return Message :: " + getProductResponse.getResultMessage().getMessage());
System.out.println("------------------- Inventory -------------------");
}
private static void enableWSAddressing(Client client) {
AddressingProperties maps = new AddressingPropertiesImpl();
EndpointReferenceType ref = new EndpointReferenceType();
AttributedURIType add = new AttributedURIType();
add.setValue("http://www.wsdoamin.com/tssamplex509/getproduct");
ref.setAddress(add);
maps.setReplyTo(ref);
maps.setFaultTo(ref);
maps.exposeAs(VersionTransformer.Names200408.WSA_NAMESPACE_NAME);
client.getRequestContext().put("javax.xml.ws.addressing.context", maps);
}
private static void enableWsSecurity(Client client) {
Properties properties = new Properties();
properties.put("org.apache.ws.security.crypto.provider","org.apache.ws.security.components.crypto.Merlin");
properties.put("org.apache.ws.security.crypto.merlin.keystore.type","jks");
properties.put("org.apache.ws.security.crypto.merlin.keystore.password","changeit");
properties.put("org.apache.ws.security.crypto.merlin.keystore.alias","ts_p&s_ws");
properties.put("org.apache.ws.security.crypto.merlin.file", "cert/TS_P&S_WS.jks");
Map<String, Object> outProps = new HashMap<String, Object>();
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
outProps.put(WSHandlerConstants.USER, "ts_p&s_ws");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS,ANSAuthenticationHandler.class.getName());
outProps.put("cryptoProperties", properties);
outProps.put(WSHandlerConstants.SIG_PROP_REF_ID,"cryptoProperties");
outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
client.getEndpoint().getOutInterceptors().add(new WSS4JOutInterceptor(outProps));
client.getEndpoint().getOutInterceptors().add(new org.apache.cxf.interceptor.LoggingOutInterceptor());
client.getEndpoint().getInInterceptors().add(new org.apache.cxf.interceptor.LoggingInInterceptor());
}
private static void addSOAPHeader(Client client) throws JAXBException {
List<Header> headers = new ArrayList<Header>();
AuthHeader authHeader = new AuthHeader();
authHeader.setUsername("ts");
authHeader.setPassword("46u43242bw3670");
SoapHeader tokenHeader = new SoapHeader(new QName("http://www.wsdoamin.com/tssamplex509", "AuthHeader"), authHeader,new JAXBDataBinding(AuthHeader.class));
headers.add(tokenHeader);
client.getRequestContext().put(Header.HEADER_LIST, headers);
}
}
ANSAuthenticationHandler.java
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import org.apache.ws.security.WSPasswordCallback;
public class ANSAuthenticationHandler extends Authenticator implements CallbackHandler {
private String proxyUser;
private String proxyPassword;
public ANSAuthenticationHandler() {
super();
}
public ANSAuthenticationHandler(String proxyUser, String proxyPassword) {
super();
this.proxyUser = proxyUser;
this.proxyPassword = proxyPassword;
}
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException
{
WSPasswordCallback pc = (WSPasswordCallback) callbacks[0];
System.err.println("CallbackHandler providing password for :: "+pc.getIdentifier());
if ("ts_p&s_ws".equals(pc.getIdentifier())) {
pc.setPassword("changeit");
}
}
public PasswordAuthentication getPasswordAuthentication()
{
System.err.println("Feeding username and password for ["+getRequestingPrompt()+"] to ["+getRequestingHost()+":"+getRequestingPort()+"] for ["+getRequestingScheme()+"] scheme");
return (new PasswordAuthentication(proxyUser, proxyPassword.toCharArray()));
}
}