8 Replies Latest reply on Aug 16, 2006 9:51 AM by acxjbertr

    Using WSSecurityHandlerOutbound in a DII client

    acxjbertr

      I've got a DII client coded up and everything works as expected. However, now I am trying to test my WS-Security setup. My JBoss server (4.0.4 with JBossWS 1.0.2) requires WS-Security signatures on all incoming SOAP messages. It accurately denies my invocations if I don't sign my messages, but now I want to make it accept my messages. I have read elsewhere that I need to configure a handler to sign my outgoing messages. I have tried to do this in the code below:

      package com.mycompany.client.test.ws;
      
      import ...
      
      public class WSTestCase extends TestCase {
       private String testDescription = null;
      
       // Possible Outputs
       private String exceptionThrown = null;
      
       public void testPlanStep1() throws MalformedURLException, ServiceException {
       go(getInput());
       }
      
       private void go(Echo request) throws ServiceException, MalformedURLException {
       try {
       ClientStuffEndpoint clientStuffEndpoint = getEndpoint();
       EchoResponse echoResponse = clientStuffEndpoint.echo(request);
      
       ClientStuffReply clientStuffReply = echoResponse.getResult();
       System.out.println(clientStuffReply.getAuditId());
       } catch (Exception e) {
       e.printStackTrace();
       assertTrue(false);
       }
       }
      
       private ClientStuffEndpoint getEndpoint() throws MalformedURLException, ServiceException, InvalidRequestException, SystemUnavailableException, RemoteException {
       ServiceFactoryImpl factory = new ServiceFactoryImpl();
       ClassLoader cl = Thread.currentThread().getContextClassLoader();
       URL wsdlLocation = cl.getResource("wsdl/ClientStuff.wsdl");
       URL mappingLocation = cl.getResource("client-mapping.xml");
       QName serviceName = new QName("http://client.mycompany.com/clientstuff/1.0", "ClientStuff");
       ServiceImpl service = (ServiceImpl) factory.createService(wsdlLocation, serviceName, mappingLocation);
       setupHandlerRegistry(service);
       return (ClientStuffEndpoint) service.getPort(ClientStuffEndpoint.class);
       }
      
       private Echo getInput() {
       Echo echoInput = new Echo();
       ClientStuffRequest clientStuffRequest = new ClientStuffRequest();
       clientStuffRequest.setAuditId("eggie");
       echoInput.setClientStuffRequest_1(clientStuffRequest);
      
       return echoInput;
       }
      
       private void setupHandlerRegistry(ServiceExt service) {
       List<HandlerInfo> clientHandlerChain = new ArrayList<HandlerInfo>();
       HandlerInfo handler = new HandlerInfo();
       handler.setHandlerClass(WSSecurityHandlerOutbound.class);
       clientHandlerChain.add(handler);
       QName securityName = new QName(org.jboss.ws.wsse.WSS_SOAP_NS, "ClientStuffEndpointPort");
       service.getDynamicHandlerRegistry().setHandlerChain(securityName, clientHandlerChain);
       }
      }
      


      Unfortunately my messages still aren't being signed.

      I was unsure about what to put on the line
      QName securityName = new QName(org.jboss.ws.wsse.WSS_SOAP_NS, "ClientStuffEndpointPort");
      and I think this might be the cause of the problem. Can anyone advise me of the correct values here? I have tried several different values from the org.jboss.ws.wsse package.

      Any help would be greatly appreciated. Thanks!

        • 1. Re: Using WSSecurityHandlerOutbound in a DII client
          acxjbertr

          My references to

          org.jboss.ws.wsse.WSS_SOAP_NS

          should actually be to
          org.jboss.ws.wsse.Constants.WSS_SOAP_NS

          I apologize for any confusion.

          • 2. Re: Using WSSecurityHandlerOutbound in a DII client
            acxjbertr

            I got it working. Here is the DII code:

            package com.mycompany.client.test.ws;
            
            import java.net.MalformedURLException;
            import java.net.URL;
            import java.rmi.RemoteException;
            import java.util.ArrayList;
            import java.util.List;
            
            import javax.xml.namespace.QName;
            import javax.xml.rpc.ServiceException;
            import javax.xml.rpc.handler.HandlerInfo;
            
            import junit.framework.TestCase;
            
            import org.jboss.ws.jaxrpc.ServiceExt;
            import org.jboss.ws.jaxrpc.ServiceFactoryImpl;
            import org.jboss.ws.jaxrpc.ServiceImpl;
            import org.jboss.ws.wsse.WSSecurityHandlerOutbound;
            
            import ...
            
            public class WSTestCase extends TestCase {
             private static final String SERVICE_NAMESPACE = "http://client.mycompany.com/clientstuff/1.0";
            
             private String testDescription = null;
            
             // Possible Outputs
             private String exceptionThrown = null;
            
             public void testPlanStep1() throws MalformedURLException, ServiceException {
             go(getInput());
             }
            
             private void go(Echo request) throws ServiceException, MalformedURLException {
             System.out.println("\n" + this.testDescription + "\n");
             displayTestInput(request);
            
             String expectedOutput = determineExpectedOutput();
             try {
             ClientServiceEndpoint clientServiceEndpoint = getEndpoint();
             EchoResponse echoResponse = clientServiceEndpoint.echo(request);
            
             ClientServiceReply clientServiceReply = echoResponse.getResult();
             System.out.println(clientServiceReply.getAuditId());
            
             } catch (Exception e) {
             String exceptionThrown = e.getClass().getName();
             displayOutput(expectedOutput, exceptionThrown);
             displayResult(exceptionThrown.equals(expectedOutput));
             e.printStackTrace();
             assertTrue(false);
             }
             }
            
             private ClientServiceEndpoint getEndpoint() throws MalformedURLException, ServiceException, InvalidRequestException, SystemUnavailableException, RemoteException {
             ServiceFactoryImpl factory = new ServiceFactoryImpl();
             ClassLoader cl = Thread.currentThread().getContextClassLoader();
             URL wsdlLocation = new URL("http://localhost:8080/clientService/ClientService?wsdl");
             URL mappingLocation = cl.getResource("client-mapping.xml");
             URL securityLocation = cl.getResource("jboss-wsse-client.xml");
             QName serviceName = new QName(SERVICE_NAMESPACE, "ClientService");
             ServiceImpl service = (ServiceImpl) factory.createService(wsdlLocation, serviceName, mappingLocation, securityLocation);
             setupWSSecurityHandler(service);
             return (ClientServiceEndpoint) service.getPort(ClientServiceEndpoint.class);
             }
            
             private Echo getInput() {
             Echo echoInput = new Echo();
             ClientServiceRequest clientServiceRequest = new ClientServiceRequest();
             clientServiceRequest.setAuditId("eggie");
             echoInput.setClientServiceRequest_1(clientServiceRequest);
            
             return echoInput;
             }
            
             private void setupWSSecurityHandler(ServiceExt service) {
             List<HandlerInfo> clientHandlerChain = new ArrayList<HandlerInfo>();
             HandlerInfo handler = new HandlerInfo();
             handler.setHandlerClass(WSSecurityHandlerOutbound.class);
             clientHandlerChain.add(handler);
             QName securityName = new QName(SERVICE_NAMESPACE, "ClientStuffEndpointPort");
             service.getDynamicHandlerRegistry().setHandlerChain(securityName, clientHandlerChain);
             }
            }
            
            


            Notice the use of the jboss-wsse-client.xml file as input to the createService method.

            Here is my jboss-wsse-client.xml:

            <?xml version="1.0" encoding="UTF-8"?>
            <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
             <key-store-file>wsse.keystore</key-store-file>
             <key-store-password>jbossws</key-store-password>
             <trust-store-file>wsse.truststore</trust-store-file>
             <trust-store-password>jbossws</trust-store-password>
             <config>
             <sign type="x509v3" alias="wsse" />
             <requires>
             <signature />
             </requires>
             </config>
            </jboss-ws-security>


            Of course, I used the keystore and truststore from the JBossWS 1.0.2 sample archive.

            • 3. Re: Using WSSecurityHandlerOutbound in a DII client
              shadens

               

              "acxjbertr" wrote:
              I got it working. Here is the DII code:


              Thank you very very very very much!
              I'm studying your DII client but I still can't sole my problems.

              I see that you use a "client-mapping.xml": what do it contains? :)

              Thanks for helping me!



              • 4. Re: Using WSSecurityHandlerOutbound in a DII client
                acxjbertr

                My client-mapping.xml file is generated by wstools. Here is the Ant task that performs the generation:

                <!-- Define a taskdef for the wstools ant task -->
                 <taskdef name="wstools" classname="org.jboss.ws.tools.ant.wstools">
                 <classpath refid="build.classpath" />
                 </taskdef>
                
                 <target name="generate.ws.client">
                 <wstools dest="${dir.gend}" config="wstools-client-config.xml" />
                 </target>


                Note that the build.classpath contains jbossws-client.jar.

                Here is the wstools-client-config.xml:

                <?xml version="1.0" encoding="UTF-8"?>
                <configuration xmlns:jbos="http://www.jboss.org/jbossws-tools">
                 <wsdl-java file="wsdl/ClientService.wsdl">
                 <mapping file="client-mapping.xml"/>
                 </wsdl-java>
                </configuration>


                All the task does is look at my WSDL file and generate the client-mapping.xml. This client-mapping.xml file contains information about how to map XML to Java objects.

                Does that answer your question?

                • 5. Re: Using WSSecurityHandlerOutbound in a DII client
                  shadens

                   

                  "acxjbertr" wrote:
                  My client-mapping.xml file is generated by wstools. Here is the Ant task that performs the generation:

                  <!-- Define a taskdef for the wstools ant task -->
                   <taskdef name="wstools" classname="org.jboss.ws.tools.ant.wstools">
                   <classpath refid="build.classpath" />
                   </taskdef>
                  
                   <target name="generate.ws.client">
                   <wstools dest="${dir.gend}" config="wstools-client-config.xml" />
                   </target>


                  Note that the build.classpath contains jbossws-client.jar.

                  Here is the wstools-client-config.xml:

                  <?xml version="1.0" encoding="UTF-8"?>
                  <configuration xmlns:jbos="http://www.jboss.org/jbossws-tools">
                   <wsdl-java file="wsdl/ClientService.wsdl">
                   <mapping file="client-mapping.xml"/>
                   </wsdl-java>
                  </configuration>


                  All the task does is look at my WSDL file and generate the client-mapping.xml. This client-mapping.xml file contains information about how to map XML to Java objects.

                  Does that answer your question?


                  Thanks for fast reply! :_)
                  And yes, it answer my question :)
                  I'm starting to understand my errors.

                  Uhm uhm... Tomorrow I have to restart with all examples :(

                  The problem is that I'm working with some differences: for example, I use jsr-181 specification; and my DII client is very different from yours. Then, I have to connect from a client to a session bean and from this I'm connect to WS (ws is within a ejb.... O_o).
                  So, I often don't understand what I have to "take" from guide and what I have not to consider...

                  I go to home... now I'm very tired. I hope to find forces tomorrow :P

                  Greetings from Italy! ;)






                  • 6. Re: Using WSSecurityHandlerOutbound in a DII client
                    shadens

                    Uff.. I don't know how to adapt examples and suggestions to my source code :(

                    I have a DII client that works fine without ws-security (sure, also web service without ws-security).

                    Follow copy/paste my code...
                    maybe, you are some idea about how "transform" my DII client for contacting a "secure" webservice (ws-security, chapter 14).

                    In any case, I can deploy also dii client within AS if this solve problem :(

                    public void WhatTimeAccessDII()
                     {
                     String endpoint = "http://notebook:8080/July-EjbWs-181/TimeBean";
                     String qnameService = "WhatTimeService";
                     String qnamePort = "ClockTime";
                     String BODY_NAMESPACE_VALUE = "http://src/jaws";
                     String ENCODING_STYLE_PROPERTY = "javax.xml.rpc.encodingstyle.namespace.uri";
                     String NS_XSD = "http://www.w3.org/2001/XMLSchema";
                     String URI_ENCODING = "http://schemas.xmlsoap.org/soap/encoding/";
                    
                     try {
                     ServiceFactory factory = ServiceFactory.newInstance();
                     Service service = factory.createService(new QName(qnameService));
                    
                     QName port = new QName(qnamePort);
                    
                     //create JAX-RPC Call using JAX-RPC Service's createCall() method.
                     Call call = service.createCall(port);
                    
                     // Configure your Call instance with its setter methods
                     call.setTargetEndpointAddress(endpoint);
                     call.setProperty(Call.SOAPACTION_USE_PROPERTY, new Boolean(true));
                     call.setProperty(Call.SOAPACTION_URI_PROPERTY, "");
                     call.setProperty(ENCODING_STYLE_PROPERTY, URI_ENCODING);
                     QName QNAME_TYPE_STRING = new QName(NS_XSD, "string");
                     call.setOperationName(new QName(BODY_NAMESPACE_VALUE, "whatTimeIsIt"));
                     call.setReturnType(QNAME_TYPE_STRING);
                    
                     call.addParameter("String_1", QNAME_TYPE_STRING, ParameterMode.IN);
                     String[] params = { "Dr. Emmet Brown " };
                    
                     // Invoke the WS operation using the JAX-RPC Call's invoke method
                     String result = (String) call.invoke(params);
                    
                     System.out.println(result);
                    
                     } catch (SOAPFaultException ex) {
                     System.out.println("Error about Soap messages.");
                     ex.printStackTrace();
                     } catch (RemoteException e) {
                     System.out.println("Errore sulla call.invoke");
                     e.printStackTrace();
                     } catch (ServiceException e) {
                     System.out.println("Errore sulla Service o createService");
                     e.printStackTrace();
                     }
                     }
                    

                    How can I add to this client ws-security features? I follow jbossWS guide but I don't succeed.
                    I repeat: in the worst of case, I can also deploy client into AS ;)

                    Heeeeeeeeeeeeeeeeeeeeeeeeeeeeelp!!

                    :_(




                    • 7. Re: Using WSSecurityHandlerOutbound in a DII client
                      kristof_taveirne

                      Hi,

                      I"m trying to do the exact same thing.
                      I'm trying to sign my xml message before sending it to the web service.

                      My code is almost identical to yours, but it doesn't sign the message at all.

                      Could somebody recheck this code. I have my doubts about these lines of code:
                      QName securityName = new QName(SERVICE_NAMESPACE, "ClientStuffEndpointPort");
                      service.getDynamicHandlerRegistry().setHandlerChain(securityName, clientHandlerChain);

                      Is there something else I need to get done to get this handler up and running?

                      I'm outa ideas...
                      Kristof,
                      Thanks!

                      • 8. Re: Using WSSecurityHandlerOutbound in a DII client
                        acxjbertr

                        Using a handler chain is the correct way of signing/encrypting your messages - whatever the code might look like to accomplish it. The lines of code that you asked about are correct given the SERVICE_NAMESPACE that you are using is the same one you use when create the QName for your service (which you then pass into createService()) and the "ClientStuffEndpointPort" corresponds to the name of your endpoint. Those lines of code are telling JBossWS to apply the WSSecurityHandlerOutbound handler to the invocation of "ClientStuffEndpointPort."

                        Also, make sure you are giving your wsse-client configuration file to the "createService" method:

                        URL securityLocation = cl.getResource("jboss-wsse-client.xml");
                        QName serviceName = new QName(SERVICE_NAMESPACE, "ClientService");
                        ServiceImpl service = (ServiceImpl) factory.createService(wsdlLocation, serviceName, mappingLocation, securityLocation);
                        


                        Here is my jboss-wsse-client.xml:

                        <?xml version="1.0" encoding="UTF-8"?>
                        <jboss-ws-security xmlns="http://www.jboss.com/ws-security/config"
                         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                         xsi:schemaLocation="http://www.jboss.com/ws-security/config http://www.jboss.com/ws-security/schema/jboss-ws-security_1_0.xsd">
                         <key-store-file>wsse.keystore</key-store-file>
                         <key-store-password>jbossws</key-store-password>
                         <trust-store-file>wsse.truststore</trust-store-file>
                         <trust-store-password>jbossws</trust-store-password>
                         <config>
                         <sign type="x509v3" alias="wsse" />
                         <requires>
                         <signature />
                         </requires>
                         </config>
                        </jboss-ws-security>


                        I am using the keystore and truststore from jbossws-1.0.2 examples archive.

                        I hope this helps.