0

我们的应用程序是 Web 服务的消费者,它要求我们在请求 SOAP 标头中实现数字签名(基于 X.509)。我们需要在标题标签中添加<ds:SignedInfo>, <wsse:BinarySecurityToken>, <ds:CanonicalizationMethod>. 它实际上与此处的 xml 非常相似。

现在,作为客户端,我们没有使用 clientgen。服务器端也不愿意将其变成 WS-Policy。我在 Oracle 文档中进行了很多搜索,但似乎以服务器端需要将此策略强制执行到 Web 服务的假设结束。那不可能发生。我们也不能使用客户端策略,因为我在 Oracle 网站上遇到的示例似乎表明它仅适用于通过 clientgen 生成的客户端代码,而我们的代码使用 ServiceControl。

就在今天,我遇到了 WSS4J,但我不确定这是否是我正在寻找的答案。这当然看起来是合理的,但它会在我的场景中工作(考虑到我们有 Weblogic ServiceController),而 WSS4J 的所有示例似乎都使用 Axis。

最近几天我一直在寻找这个,我已经到了沮丧的地步。请帮忙!

谢谢,阿克

4

1 回答 1

0

我遇到了同样的问题,最后我们使用 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()));
             }
            }
于 2013-10-21T00:17:45.877 回答