2 Replies Latest reply on May 16, 2008 7:48 AM by Alessio Soldano

    Problem running WS with p a r t i a l encryption

    lall lall Newbie

      Hi,

      I am trying to implement a Web Service with partial encryption of SOAP body payload elements and their contents.

      Unfortunately I do not get it to work.

      The Web Service works smoothly with full payload encryption using the standard WS-Security configs jboss-wsse-client.xml and jboss-wsse-server.xml:

      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">
       <config>
       <timestamp ttl="30"/>
       <sign type="x509v3" alias="wsse" includeTimestamp="true"/>
       <encrypt type="x509v3" alias="InitialServerCert"/>
       <requires>
       <signature/>
       <encryption/>
       </requires>
       </config>
       <timestamp-verification createdTolerance="500" warnCreated="true" expiresTolerance="100" warnExpires="true"/>
      </jboss-ws-security>
      



      jboss-wsse-server.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">
       <key-store-file>WEB-INF/InitialServerKeyStore.jks</key-store-file>
       <key-store-password>123</key-store-password>
       <trust-store-file>WEB-INF/InitialServerTrustStore.jks</trust-store-file>
       <trust-store-password>123</trust-store-password>
       <config>
       <timestamp ttl="30"/>
       <sign type="x509v3" alias="wsse" includeTimestamp="true"/>
       <encrypt type="x509v3" alias="InitialClientCert"/>
       <requires>
       <signature/>
       <encryption/>
       </requires>
       </config>
       <timestamp-verification createdTolerance="500" warnCreated="true" expiresTolerance="100" warnExpires="true"/>
      </jboss-ws-security>
      


      The WS impl class looks as follows:

      package com.spg.std.ws.security;
      
      import javax.jws.Oneway;
      import javax.jws.WebMethod;
      import javax.jws.WebParam;
      import javax.jws.WebResult;
      import javax.jws.WebService;
      import javax.jws.soap.SOAPBinding;
      
      import org.apache.commons.logging.Log;
      import org.apache.commons.logging.LogFactory;
      import org.jboss.ws.annotation.EndpointConfig;
      
      
      @WebService(name = "SecurityWS", targetNamespace = "http://std.spg.com/ws/security",
       serviceName = "SecurityService", wsdlLocation = "WEB-INF/wsdl/SecurityService.wsdl")
      @SOAPBinding(style = SOAPBinding.Style.DOCUMENT)
      @EndpointConfig(configName = "Standard WSSecurity Endpoint")
      public class SecurityWSImpl {
      
       @WebMethod(operationName="findProfile", action = "http://std.spg.com/ws/security/findProfile")
       @WebResult(name="profile", partName="profile", targetNamespace="http://std.spg.com/ws/security/vo")
       public ProfileDT findProfile(@WebParam(name = "score", partName = "score", targetNamespace="http://std.spg.com/ws/security/vo") float score) {
       log.debug("findProfile() input score: "+score);
      
       ProfileDT profile = new ProfileDT();
       profile.getAddresses().add(new AddressDT("one1", 67678, "two1", "three1", "four1"));
       profile.getAddresses().add(new AddressDT("one2", 45674, "two2", "three2", "four2"));
      
       ScoreDataDT scoreData = new ScoreDataDT("04568045z6983450", score, 126);
       profile.setScoreData(scoreData);
      
       profile.setProfileid("sp0df79sg60dfg780dfg70");
      
       return profile;
       }
      
       @WebMethod(operationName="sendProfile", action = "http://std.spg.com/ws/security/sendProfile")
       @Oneway
       public void sendProfile(@WebParam(name = "profile", partName = "profile", targetNamespace="http://std.spg.com/ws/security/vo") ProfileDT profile,
       @WebParam(name = "dateString", partName = "dateString", targetNamespace="http://std.spg.com/ws/security/vo") String dateString) {
       log.debug("sendProfile() profile: "+profile);
       }
      
       private Log log = LogFactory.getLog(getClass());
      }
      


      The WSDL generated with the ant tag wsprovide and manually modified according to http://wiki.jboss.org/wiki/WSSecurityComplexExample, looks as follows:

      <?xml version="1.0" encoding="UTF-8"?>
      <definitions name='SecurityService' targetNamespace='http://std.spg.com/ws/security' xmlns='http://schemas.xmlsoap.org/wsdl/' xmlns:ns1='http://std.spg.com/ws/security/vo' xmlns:soap='http://schemas.xmlsoap.org/wsdl/soap/' xmlns:tns='http://std.spg.com/ws/security' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>
       <types>
       <xs:schema elementFormDefault='qualified' attributeFormDefault='qualified' targetNamespace='http://std.spg.com/ws/security/vo' version='1.0' xmlns:ns1='http://std.spg.com/ws/security' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
       <xs:import namespace='http://std.spg.com/ws/security'/>
       <xs:element name='dateString' form='qualified' type='xs:string'/>
       <xs:element name='profile' form='qualified' type='ns1:ProfileDT'/>
       <xs:element name='score' form='qualified' type='xs:float'/>
       </xs:schema>
       <xs:schema targetNamespace='http://std.spg.com/ws/security' version='1.0' xmlns:ns1='http://std.spg.com/ws/security/vo' xmlns:tns='http://std.spg.com/ws/security' xmlns:xs='http://www.w3.org/2001/XMLSchema'>
       <xs:import namespace='http://std.spg.com/ws/security/vo'/>
       <xs:element name='findProfile' type='tns:findProfile'/>
       <xs:element name='findProfileResponse' type='tns:findProfileResponse'/>
       <xs:element name='profileDT' type='tns:ProfileDT'/>
       <xs:element name='sendProfile' type='tns:sendProfile'/>
       <xs:complexType name='findProfile'>
       <xs:sequence>
       <xs:element ref='ns1:score'/>
       </xs:sequence>
       </xs:complexType>
       <xs:complexType name='findProfileResponse'>
       <xs:sequence>
       <xs:element minOccurs='0' ref='ns1:profile'/>
       </xs:sequence>
       </xs:complexType>
       <xs:complexType name='ProfileDT'>
       <xs:sequence>
       <xs:element minOccurs='0' name='addresses' form='qualified'>
       <xs:complexType>
       <xs:sequence>
       <xs:element maxOccurs='unbounded' minOccurs='0' name='address' form='qualified' type='tns:AddressDT'/>
       </xs:sequence>
       </xs:complexType>
       </xs:element>
       <xs:element minOccurs='0' name='profileid' form='qualified' type='xs:string'/>
       <xs:element minOccurs='0' name='scoredata' form='qualified' type='tns:ScoreDataDT'/>
       </xs:sequence>
       </xs:complexType>
       <xs:complexType name='AddressDT'>
       <xs:sequence>
       <xs:element minOccurs='0' name='addresstype' form='qualified' type='xs:string'/>
       <xs:element minOccurs='0' name='email' form='qualified' type='xs:string'/>
       <xs:element minOccurs='0' name='phone' form='qualified' type='xs:string'/>
       <xs:element name='postalcode' form='qualified' type='xs:int'/>
       <xs:element minOccurs='0' name='street' form='qualified' type='xs:string'/>
       </xs:sequence>
       </xs:complexType>
       <xs:complexType name='ScoreDataDT'>
       <xs:sequence>
       <xs:element minOccurs='0' name='clientid' form='qualified' type='xs:string'/>
       <xs:element name='count' form='qualified' type='xs:int'/>
       <xs:element name='score' form='qualified' type='xs:float'/>
       </xs:sequence>
       </xs:complexType>
       <xs:complexType name='sendProfile'>
       <xs:sequence>
       <xs:element minOccurs='0' ref='ns1:profile'/>
       <xs:element minOccurs='0' ref='ns1:dateString'/>
       </xs:sequence>
       </xs:complexType>
       </xs:schema>
       </types>
       <message name='SecurityWS_findProfile'>
       <part element='tns:findProfile' name='findProfile'/>
       </message>
       <message name='SecurityWS_findProfileResponse'>
       <part element='tns:findProfileResponse' name='findProfileResponse'/>
       </message>
       <message name='SecurityWS_sendProfile'>
       <part element='tns:sendProfile' name='sendProfile'/>
       </message>
       <portType name='SecurityWS'>
       <operation name='findProfile' parameterOrder='findProfile'>
       <input message='tns:SecurityWS_findProfile'/>
       <output message='tns:SecurityWS_findProfileResponse'/>
       </operation>
       <operation name='sendProfile'>
       <input message='tns:SecurityWS_sendProfile'/>
       </operation>
       </portType>
       <binding name='SecurityWSBinding' type='tns:SecurityWS'>
       <soap:binding style='document' transport='http://schemas.xmlsoap.org/soap/http'/>
       <operation name='findProfile'>
       <soap:operation soapAction='http://std.spg.com/ws/security/findProfile'/>
       <input>
       <soap:body use='literal'/>
       </input>
       <output>
       <soap:body use='literal'/>
       </output>
       </operation>
       <operation name='sendProfile'>
       <soap:operation soapAction='http://std.spg.com/ws/security/sendProfile'/>
       <input>
       <soap:body use='literal'/>
       </input>
       </operation>
       </binding>
       <service name='SecurityService'>
       <port binding='tns:SecurityWSBinding' name='SecurityWSPort'>
       <soap:address location='http://localhost:8081/SecurityService'/>
       </port>
       </service>
      </definitions>
      


      After deploying the WS and running the client by calling SecurityWSImpl.findProfile(float) returning a ProfileDT object,
      using the generated WS artifacts of the ant tag wsconsume, the payload is not encrypted at all:

      soap request message:
      POST /SecurityService HTTP/1.1
      SOAPAction: "http://std.spg.com/ws/security/findProfile"
      Content-Type: text/xml; charset=UTF-8
      JBoss-Remoting-Version: 22
      User-Agent: JBossRemoting - 2.2.2.SP1 (Bluto)
      Host: localhost:8081
      Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
      Connection: keep-alive
      Content-Length: 269
      
      <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
       <env:Header/>
       <env:Body>
       <ns1:findProfile xmlns="http://std.spg.com/ws/security/vo" xmlns:ns1="http://std.spg.com/ws/security">
       <score>45.78</score>
       </ns1:findProfile>
       </env:Body>
      </env:Envelope>
      


      soap response message:
      HTTP/1.1 200 OK
      Server: Apache-Coyote/1.1
      X-Powered-By: Servlet 2.4; JBoss-4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)/Tomcat-5.5
      Content-Type: text/xml;charset=UTF-8
      Transfer-Encoding: chunked
      Date: Wed, 14 May 2008 07:25:01 GMT
      
      <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
       <env:Header/>
       <env:Body>
       <ns3:findProfileResponse xmlns:ns2="http://std.spg.com/ws/security/vo" xmlns:ns3="http://std.spg.com/ws/security">
       <ns2:profile>
       <addresses>
       <address>
       <addresstype>four1</addresstype>
       <email>three1</email>
       <phone>two1</phone>
       <postalcode>67678</postalcode>
       <street>one1</street>
       </address>
       <address>
       <addresstype>four2</addresstype>
       <email>three2</email>
       <phone>two2</phone>
       <postalcode>45674</postalcode>
       <street>one2</street>
       </address>
       </addresses>
       <profileid>sp0df79sg60dfg780dfg70</profileid>
       <scoredata>
       <clientid>04568045z6983450</clientid>
       <count>0</count>
       <score>45.78</score>
       </scoredata>
       </ns2:profile>
       </ns3:findProfileResponse>
       </env:Body>
      </env:Envelope>
      


      To find the reason, why there is no encryption, I turned on debugging of JBoss and on client side:

      ...
      DEBUG [XMLContent] objectValue: com.spg.std.ws.security.jaxws.FindProfile
      DEBUG [SOAPContentElement] -----------------------------------
      DEBUG [EndpointInvocation] transformPayloadValue: org.jboss.ws.core.soap.SOAPBodyElementDoc -> com.spg.std.ws.security.jaxws.FindProfile
      DEBUG [ParameterWrapping] unwrapRequestParameters: com.spg.std.ws.security.jaxws.FindProfile
      DEBUG [SecurityWSImpl] findProfile() input score: 45.78
      DEBUG [EndpointInvocation] setReturnValue: com.spg.std.ws.security.ProfileDTDEBUG [MessageContextJAXWS] Begin response processing
      DEBUG [MessageContextAssociation] popMessageContext: org.jboss.ws.core.jaxws.handler.SOAPMessageContextJAXWS@7a279c (Thread http-127.0.0.1-8080-1)
      DEBUG [MessageContextAssociation] pushMessageContext: org.jboss.ws.core.jaxws.handler.SOAPMessageContextJAXWS@1be91c8 (Thread http-127.0.0.1-8080-1)
      DEBUG [SOAP11BindingJAXWS] bindResponseMessage: {http://std.spg.com/ws/security}findProfile
      DEBUG [EndpointInvocation] getReturnValue
      DEBUG [EndpointInvocation] transformPayloadValue: com.spg.std.ws.security.ProfileDT -> com.spg.std.ws.security.ProfileDT
      DEBUG [ParameterWrapping] wrapResponseParameter: com.spg.std.ws.security.jaxws.FindProfileResponse
      DEBUG [EndpointInvocation] setReturnValue: org.jboss.ws.core.soap.SOAPBodyElementDoc
      DEBUG [HandlerDelegateJAXWS] callResponseHandlerChain: PRE
      DEBUG [HandlerDelegateJAXWS] callResponseHandlerChain: ENDPOINT
      DEBUG [HandlerDelegateJAXWS] callResponseHandlerChain: POST
      DEBUG [HandlerChainExecutor] Enter: handleOutBoundMessage
      DEBUG [WSSecurityDispatcher] WS-Security config: null
      DEBUG [HandlerChainExecutor] Exit: handleOutBoundMessage with status: true
      DEBUG [HandlerDelegateJAXWS] closeHandlerChain
      DEBUG [HandlerChainExecutor] close
      DEBUG [HandlerDelegateJAXWS] closeHandlerChain
      DEBUG [HandlerChainExecutor] close
      DEBUG [HandlerDelegateJAXWS] closeHandlerChain
      DEBUG [HandlerChainExecutor] close
      DEBUG [SOAPContentElement] -----------------------------------
      DEBUG [SOAPContentElement] Transitioning from OBJECT_VALID to XML_VALID
      DEBUG [ObjectContent] getXMLFragment from Object [xmlType={http://std.spg.com/ws/security}findProfileResponse,javaType=class com.spg.std.ws.security.jaxws.FindProfileResponse]
      ...
      


      WS client debug:
      ...
      DEBUG [ParameterWrapping] wrapRequestParameters: com.spg.std.ws.security.FindProfile
      DEBUG [EndpointInvocation] setRequestParamValue: [name={http://std.spg.com/ws/security}findProfile,value=com.spg.std.ws.security.FindProfile]
      DEBUG [EndpointInvocation] getRequestParamValue: {http://std.spg.com/ws/security}findProfile
      DEBUG [EndpointInvocation] transformPayloadValue: com.spg.std.ws.security.FindProfile -> com.spg.std.ws.security.FindProfile
      DEBUG [WSSecurityConfigFactory] createConfiguration from: jar:file:/D:/home/simon/main/java/01102007/projekte/ws/SecurityWSProject/dist/SecurityWSClient.jar!/META-INF/jboss-wsse-client.xml
      DEBUG [WSSecurityDispatcher] WS-Security config: null
      DEBUG [HTTPRemotingConnection] Get locator for: [addr=http://localhost:8081/SecurityService,props={javax.xml.ws.service.endpoint.address=http://localhost:8081/SecurityService}]
      DEBUG [HTTPRemotingConnection] Remoting metadata: {HEADER={SOAPAction="http://std.spg.com/ws/security/findProfile", Content-Type=text/xml; charset=UTF-8}, NoThrowOnError=true}
      DEBUG [SOAPContentElement] -----------------------------------
      DEBUG [SOAPContentElement] Transitioning from OBJECT_VALID to XML_VALID
      DEBUG [ObjectContent] getXMLFragment from Object [xmlType={http://std.spg.com/ws/security}findProfile,javaType=class com.spg.std.ws.security.FindProfile]
      DEBUG [ObjectContent] xmlFragment: [source=<ns1:findProfile xmlns="http://std.spg.com/ws/security/vo" xmlns:ns1="http://std.spg.com/ws/security"><score>45.78</score></ns1:findProfile>]
      DEBUG [SOAPContentElement] -----------------------------------
      DEBUG [SOAPMessageUnMarshallerHTTP] getMimeHeaders from: {X-Powered-By=[Servlet 2.4; JBoss-4.2.2.GA (build: SVNTag=JBoss_4_2_2_GA date=200710221139)/Tomcat-5.5], ResponseCodeMessage=OK, Date=[Wed, 14 May 2008 13:07:57 GMT], Content-Type=[text/xml;charset=UTF-8], Server=[Apache-Coyote/1.1], HEADER={SOAPAction="http://std.spg.com/ws/security/findProfile", Content-Type=text/xml; charset=UTF-8}, Transfer-Encoding=[chunked], NoThrowOnError=true, ResponseCode=200}
      ...
      


      Obviously, in my opinion, the reason why there is no encryption is the debug message:
      DEBUG [WSSecurityDispatcher] WS-Security config: null on client as well as on client side. It looks to me that there is a problem with the customized jboss-wsse-client.xml and jboss-wsse-server.xml configured for partial encryption of the WS method ProfileDT SecurityWSImpl.findProfile(float). With this problem, these two files are being ignored which causes the plain text content of the soap messages. Is this right, and if so, what is wrong with: ?

      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">
       <port name="SecurityWS">
       <operation name="findProfile">
       <config>
       <timestamp ttl="30"/>
       <sign type="x509v3" alias="wsse" includeTimestamp="true">
       <targets>
       <target type="qname">{http://std.spg.com/ws/security/vo}score</target>
       </targets>
       </sign>
       <encrypt type="x509v3" alias="InitialServerCert">
       <targets>
       <target type="qname" contentOnly="true">{http://std.spg.com/ws/security/vo}score</target>
       </targets>
       </encrypt>
       <requires>
       <sign type="x509v3" alias="wsse" includeTimestamp="true">
       <targets>
       <target type="qname">{http://std.spg.com/ws/security/vo}profile</target>
       </targets>
       </sign>
       <encrypt type="x509v3" alias="InitialServerCert">
       <targets>
       <target type="qname" contentOnly="true">{http://std.spg.com/ws/security/vo}profile</target>
       </targets>
       </encrypt>
       </requires>
       </config>
       </operation>
       </port>
       <timestamp-verification createdTolerance="500" warnCreated="true" expiresTolerance="100" warnExpires="true"/>
      </jboss-ws-security>
      


      jboss-wsse-server.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">
       <key-store-file>WEB-INF/InitialServerKeyStore.jks</key-store-file>
       <key-store-password>123</key-store-password>
       <trust-store-file>WEB-INF/InitialServerTrustStore.jks</trust-store-file>
       <trust-store-password>123</trust-store-password>
       <port name="SecurityWS">
       <operation name="findProfile">
       <config>
       <timestamp ttl="30"/>
       <sign type="x509v3" alias="wsse" includeTimestamp="true">
       <targets>
       <target type="qname">{http://std.spg.com/ws/security/vo}profile</target>
       </targets>
       </sign>
       <encrypt type="x509v3" alias="InitialServerCert">
       <targets>
       <target type="qname" contentOnly="true">{http://std.spg.com/ws/security/vo}profile</target>
       </targets>
       </encrypt>
       <requires>
       <sign type="x509v3" alias="wsse" includeTimestamp="true">
       <targets>
       <target type="qname">{http://std.spg.com/ws/security/vo}score</target>
       </targets>
       </sign>
       <encrypt type="x509v3" alias="InitialServerCert">
       <targets>
       <target type="qname" contentOnly="true">{http://std.spg.com/ws/security/vo}score</target>
       </targets>
       </encrypt>
       </requires>
       </config>
       </operation>
       </port>
       <timestamp-verification createdTolerance="500" warnCreated="true" expiresTolerance="100" warnExpires="true"/>
      </jboss-ws-security>
      


      The WS Client:
       SecurityService service = new SecurityService();
       sei = service.getSecurityWSPort();
      
       System.setProperty("org.jboss.ws.wsse.keyStore", "SecurityWS/client/InitialClientKeyStore.jks");
       System.setProperty("org.jboss.ws.wsse.trustStore", "SecurityWS/client/InitialClientTrustStore.jks");
       System.setProperty("org.jboss.ws.wsse.keyStorePassword", "123");
       System.setProperty("org.jboss.ws.wsse.trustStorePassword", "123");
       System.setProperty("org.jboss.ws.wsse.keyStoreType", "jks");
       System.setProperty("org.jboss.ws.wsse.trustStoreType", "jks");
      
       ((StubExt)sei).setConfigName("Standard WSSecurity Client");
      
       ProfileDT profile = sei.findProfile(45.78f);
       log.debug(profile+" received");
      


      I read http://wiki.jboss.org/wiki/WSSecurityComplexExample which says that elements must have a form="qualified" attribute, to make it possible to find the payload parts to be encrypted within the WSDL. Since there is no possibility (?) to let wsprovide include these form="qualified" attributes into the WSDL, I first included the elementFormDefault="qualified" manually in:
      ...
      <xs:schema attributeFormDefault="qualified" elementFormDefault="qualified" targetNamespace="http://std.spg.com/ws/security/vo" version="1.0">
      ...
      


      with the idea to enable the form="qualified" globally for all WSDL elements instead of adding form="qualified" to each single element. This was not successful. After that, I tried the form="qualified" variation, also with no luck.

      So now I am suffering a shortage of ideas, what could be wrong. After a little bit of source code investigation of the WS-Security and the Xerces XML parsing implementation, I am sure the partial payload encryption is supported.

      Can someone, who already managed to get partial payload encryption working, please provide some help or hints?

      If there is additional info you need to analyze this problem, do not hesitate to ask.


      Thanks in advance,

      Andy