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.sec...]
| 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.7...>]
| 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</ta...
| </targets>
| </sign>
| <encrypt type="x509v3" alias="InitialServerCert">
| <targets>
| <target type="qname"
contentOnly="true">{http://std.spg.com/ws/security/vo}score&...
| </targets>
| </encrypt>
| <requires>
| <sign type="x509v3" alias="wsse"
includeTimestamp="true">
| <targets>
| <target
type="qname">{http://std.spg.com/ws/security/vo}profile</...
| </targets>
| </sign>
| <encrypt type="x509v3" alias="InitialServerCert">
| <targets>
| <target type="qname"
contentOnly="true">{http://std.spg.com/ws/security/vo}profil...
| </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</...
| </targets>
| </sign>
| <encrypt type="x509v3" alias="InitialServerCert">
| <targets>
| <target type="qname"
contentOnly="true">{http://std.spg.com/ws/security/vo}profil...
| </targets>
| </encrypt>
| <requires>
| <sign type="x509v3" alias="wsse"
includeTimestamp="true">
| <targets>
| <target
type="qname">{http://std.spg.com/ws/security/vo}score</ta...
| </targets>
| </sign>
| <encrypt type="x509v3" alias="InitialServerCert">
| <targets>
| <target type="qname"
contentOnly="true">{http://std.spg.com/ws/security/vo}score&...
| </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
View the original post :
http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4150748#...
Reply to the post :
http://www.jboss.com/index.html?module=bb&op=posting&mode=reply&a...