JBossWS - Stack Metro User Guide

This page covers features available in JBossWS Metro stack only. Please refer to the common user guide for a basic introduction to JAX-WS programming as well as documentation on all features, tools, etc. the JBossWS Web Service Framework provides for every supported stack (including Metro stack).

Also please note this page does not go through the documentation of every feature, option, etc. provided by GlassFish Metro; on the countrary the only topics covered here are specific issues regarding integration with JBoss and stack specific features provided by JBossWS Web Service Framework for the Metro stack. A few tutorials are also provided for show how to leverage some WS technologies.

The official GlassFish Metro documentation is available here.

 

Extended Features

WS-Addressing

Metro WS-Addressing documentation
Metro WS-Addressing Tutorial

WS-ReliableMessaging

Metro WS-ReliableMessaging documentation
Metro WS-ReliableMessaging Tutorial

WS-Policy

Metro WS-Policy documentation
Metro WS-Policy Tutorial

WS-Security

Metro comes with support for WS-Security and WS-SecurityPolicy. This means that thanks to the JBossWS-Metro integration, users can leverage the WSIT implementation of WS-Security while deploying their application on the JBoss Application Server.

WSIT security on JBoss

The Metro documentation features an interesting chapter on how to use WSIT security. Here you'll find a brief explanation on how to create a simple application and what you need to do to leverage WSIT security on JBoss.

 

Creating the web service endpoint

First of all you need to create the web service endpoint / client using JAX-WS. This can be achieved in many ways, for instance you might want to:

  1. write your endpoint implementation, then run the wsprovide tool which generates the service contract (bottom-up approach);
  2. run the wsconsume tool to get the client artifacts from the service contract (top-down approach);
  3. write your client implementation.

 

Turn on WS-Security

WSIT security is triggered through its descriptors (wsit-*.xml files) and the service contract (wsdl file) which contain policies specifying the whole configuration. You may want to leverage the Metro NetBeans integration or write down the policies by hand.

Here is an example of modified wsdl and wsit-endpoint-class.xml files with policies enforcing message signature and encryption:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wssecurity" name="SecurityService"
          xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wssecurity"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
          xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
          xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
          xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"
          xmlns:sc="http://schemas.sun.com/2006/03/wss/server"
          xmlns="http://schemas.xmlsoap.org/wsdl/">
  <types>
    <xsd:schema>
      <xsd:import namespace="http://www.jboss.org/jbossws/ws-extensions/wssecurity"
                  schemaLocation="SecurityService_schema1.xsd"/>
    </xsd:schema>
  </types>
  <message name="sayHello">
    <part name="parameters" element="tns:sayHello"/>
  </message>
  <message name="sayHelloResponse">
    <part name="parameters" element="tns:sayHelloResponse"/>
  </message>
  <portType name="ServiceIface">
    <operation name="sayHello">
      <input message="tns:sayHello"/>
      <output message="tns:sayHelloResponse"/>
    </operation>
  </portType>
  <binding name="SecurityServicePortBinding" type="tns:ServiceIface">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <wsp:PolicyReference URI="#SecurityServicePortBindingPolicy"/>
    <operation name="sayHello">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
        <wsp:PolicyReference URI="#SecurityServicePortBinding_sayHello_Policy"/>
      </input>
      <output>
        <soap:body use="literal"/>
        <wsp:PolicyReference URI="#SecurityServicePortBinding_sayHello_Policy"/>
      </output>
    </operation>
  </binding>
  <service name="SecurityService">
    <port name="SecurityServicePort" binding="tns:SecurityServicePortBinding">
      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
    </port>
  </service>
  
  <!-- Policy definitions -->
  <wsp:Policy wsu:Id="SecurityServicePortBindingPolicy">
       <wsp:ExactlyOne>
           <wsp:All>
               <sp:SymmetricBinding>
                   <wsp:Policy>
                       <sp:ProtectionToken>
                           <wsp:Policy>
                               <sp:X509Token
 sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
                                   <wsp:Policy>
                                       <sp:WssX509V3Token10/>
                                   </wsp:Policy>
                               </sp:X509Token>
                           </wsp:Policy>
                       </sp:ProtectionToken>
                       <sp:Layout>
                           <wsp:Policy>
                               <sp:Strict/>
                           </wsp:Policy>
                       </sp:Layout>
                       <sp:IncludeTimestamp/>
                       <sp:OnlySignEntireHeadersAndBody/>
                       <sp:AlgorithmSuite>
                           <wsp:Policy>
                               <sp:Basic128/>
                           </wsp:Policy>
                       </sp:AlgorithmSuite>
                   </wsp:Policy>
               </sp:SymmetricBinding>
               <sp:Wss11>
                   <wsp:Policy>
                       <sp:MustSupportRefKeyIdentifier/>
                       <sp:MustSupportRefIssuerSerial/>
                       <sp:MustSupportRefThumbprint/>
                       <sp:MustSupportRefEncryptedKey/>
                   </wsp:Policy>
               </sp:Wss11>
               <sc:KeyStore wspp:visibility="private"
                               alias="xws-security-server"
                               location="server-keystore.jks"
                               storepass="changeit"/>
               <sc:TrustStore wspp:visibility="private"
                               location="server-truststore.jks"
                               storepass="changeit"/>
           </wsp:All>
       </wsp:ExactlyOne>
    </wsp:Policy>
    <wsp:Policy wsu:Id="SecurityServicePortBinding_sayHello_Policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <sp:EncryptedParts>
                    <sp:Body/>
                </sp:EncryptedParts>
                <sp:SignedParts>
                    <sp:Body/>
                </sp:SignedParts>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
</definitions>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wssecurity" name="SecurityService"
          xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wssecurity"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
          xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
          xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy"
          xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"
          xmlns:sc="http://schemas.sun.com/2006/03/wss/server"
          xmlns="http://schemas.xmlsoap.org/wsdl/">
  <message name="sayHello"/>
  <message name="sayHelloResponse"/>
  <portType name="ServiceIface">
    <operation name="sayHello">
      <input message="tns:sayHello"/>
      <output message="tns:sayHelloResponse"/>
    </operation>
  </portType>
  <binding name="SecurityServicePortBinding" type="tns:ServiceIface">
    <soap:binding transport="http://schemas.xmlsoap.org/soap/http" style="document"/>
    <wsp:PolicyReference URI="#SecurityServicePortBindingPolicy"/>
    <operation name="sayHello">
      <soap:operation soapAction=""/>
      <input>
        <soap:body use="literal"/>
        <wsp:PolicyReference URI="#SecurityServicePortBinding_sayHello_Policy"/>
      </input>
      <output>
        <soap:body use="literal"/>
        <wsp:PolicyReference URI="#SecurityServicePortBinding_sayHello_Policy"/>
      </output>
    </operation>
  </binding>
  <service name="SecurityService">
    <port name="SecurityServicePort" binding="tns:SecurityServicePortBinding">
      <soap:address location="REPLACE_WITH_ACTUAL_URL"/>
    </port>
  </service>
  
  <!-- Policy definitions -->
  <wsp:Policy wsu:Id="SecurityServicePortBindingPolicy">
       <wsp:ExactlyOne>
           <wsp:All>
               <sp:SymmetricBinding>
                   <wsp:Policy>
                       <sp:ProtectionToken>
                           <wsp:Policy>
                               <sp:X509Token
 sp:IncludeToken="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy/IncludeToken/Never">
                                   <wsp:Policy>
                                       <sp:WssX509V3Token10/>
                                   </wsp:Policy>
                               </sp:X509Token>
                           </wsp:Policy>
                       </sp:ProtectionToken>
                       <sp:Layout>
                           <wsp:Policy>
                               <sp:Strict/>
                           </wsp:Policy>
                       </sp:Layout>
                       <sp:IncludeTimestamp/>
                       <sp:OnlySignEntireHeadersAndBody/>
                       <sp:AlgorithmSuite>
                           <wsp:Policy>
                               <sp:Basic128/>
                           </wsp:Policy>
                       </sp:AlgorithmSuite>
                   </wsp:Policy>
               </sp:SymmetricBinding>
               <sp:Wss11>
                   <wsp:Policy>
                       <sp:MustSupportRefKeyIdentifier/>
                       <sp:MustSupportRefIssuerSerial/>
                       <sp:MustSupportRefThumbprint/>
                       <sp:MustSupportRefEncryptedKey/>
                   </wsp:Policy>
               </sp:Wss11>
               <sc:KeyStore wspp:visibility="private"
                               alias="xws-security-server"
                               location="server-keystore.jks"
                               storepass="changeit"/>
               <sc:TrustStore wspp:visibility="private"
                               location="server-truststore.jks"
                               storepass="changeit"/>
           </wsp:All>
       </wsp:ExactlyOne>
    </wsp:Policy>
    <wsp:Policy wsu:Id="SecurityServicePortBinding_sayHello_Policy">
        <wsp:ExactlyOne>
            <wsp:All>
                <sp:EncryptedParts>
                    <sp:Body/>
                </sp:EncryptedParts>
                <sp:SignedParts>
                    <sp:Body/>
                </sp:SignedParts>
            </wsp:All>
        </wsp:ExactlyOne>
    </wsp:Policy>
</definitions>

Please note the latter one basically contains the same lines of the wsdl file, except for the types and the empty message elements. The security is configured through:

  • a policy attached to the binding and specifying the general configuration (algorithms, protection tokens, etc.)
  • a policy attached to the operation and specifying the security process to be performed (here signature and encryption).

The client descriptor (wsit-client.xml) is configured as follows:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<definitions targetNamespace="http://www.jboss.org/jbossws/ws-extensions/wssecurity" name="SecurityService"
          xmlns:tns="http://www.jboss.org/jbossws/ws-extensions/wssecurity"
          xmlns:xsd="http://www.w3.org/2001/XMLSchema"
          xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
          xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
          xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
          xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy"
          xmlns:sc="http://schemas.sun.com/2006/03/wss/server"
          xmlns="http://schemas.xmlsoap.org/wsdl/">
  <portType name="ServiceIface"/>
  <binding name="SecurityServicePortBinding" type="tns:ServiceIface">
    <wsp:PolicyReference URI="#ClientKeystorePolicy"/>
  </binding>
  <service name="SecurityService">
    <port name="SecurityServicePort" binding="tns:SecurityServicePortBinding"/>
  </service>
  <wsp:Policy wsu:Id="ClientKeystorePolicy" 
                  xmlns:sc="http://schemas.sun.com/2006/03/wss/client"
                 xmlns:wspp="http://java.sun.com/xml/ns/wsit/policy">
     <wsp:ExactlyOne>
         <wsp:All>
             <sc:KeyStore wspp:visibility="private"
                          location="client-keystore.jks"
                          type="JKS"
                       alias="xws-security-client"
                       storepass="changeit">
             </sc:KeyStore>
             <sc:TrustStore wspp:visibility="private" 
                          location="client-truststore.jks" 
                          type="JKS"
                          peeralias="xws-security-server"
                             storepass="changeit">
             </sc:TrustStore>
         </wsp:All>
     </wsp:ExactlyOne>
 </wsp:Policy>
</definitions>

As on server side, the keystore and trustore are configured through a couple of Sun proprietary policies.

 

Finally since Metro looks for a tomcat-users.xml file to perform authentication when not running on Glassfish server, you need to override the default com.sun.xml.wss.RealmAuthenticationAdapter. This is achieved providing a custom com.sun.xml.xwss.RealmAuthenticator file in META-INF/services; it has to contain your realm authentication class name:

org.jboss.test.ws.jaxws.samples.wsse.RealmAuthenticator

Here is that trivial sample authenticator:

package org.jboss.test.ws.jaxws.samples.wsse;

import javax.security.auth.Subject;
import com.sun.xml.wss.RealmAuthenticationAdapter;
import com.sun.xml.wss.XWSSecurityException;

public class RealmAuthenticator extends RealmAuthenticationAdapter
{
   @Override
   public boolean authenticate(Subject callerSubject, String username, String password) throws XWSSecurityException
   {
      System.out.println("Custom realm authenticator called: username=" + username + ", password=" + password);
      return (username.equals("kermit") && password.equals("thefrog"));
   }
}


Package and deploy

To deploy your web service endpoint, you need to package the following files along with your service implementation:

  • the modified wsdl contract
  • the wsit-endpoint-classname.xml descriptor
  • the keystore and truststore files (if required for signature/encryption)
  • the com.sun.xml.xwss.RealmAuthenticator file

For instance, here are the archive contents for the afore mentioned signature & encryption sample (POJO endpoint):

[alessio@localhost metro-tests]$ jar -tvf target/test-libs/jaxws-samples-wsse-sign-encrypt-50.war 
     0 Thu Jun 05 15:58:50 CEST 2008 META-INF/
   106 Thu Jun 05 15:58:48 CEST 2008 META-INF/MANIFEST.MF
     0 Thu Jun 05 15:58:50 CEST 2008 WEB-INF/
     0 Thu Jun 05 15:58:50 CEST 2008 WEB-INF/classes/
     0 Wed May 21 12:21:52 CEST 2008 WEB-INF/classes/org/
     0 Wed May 21 12:21:52 CEST 2008 WEB-INF/classes/org/jboss/
     0 Wed May 21 12:21:52 CEST 2008 WEB-INF/classes/org/jboss/test/
     0 Wed May 21 12:21:52 CEST 2008 WEB-INF/classes/org/jboss/test/ws/
     0 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/
     0 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/
     0 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/
  1202 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/RealmAuthenticator.class
   364 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/ServiceIface.class
   859 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/ServiceImpl.class
     0 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/jaxws/
   685 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/jaxws/SayHello.class
  1049 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/org/jboss/test/ws/jaxws/samples/wsse/jaxws/SayHelloResponse.class
   249 Thu Jun 05 15:58:48 CEST 2008 WEB-INF/jboss-web.xml
     0 Wed May 21 12:21:54 CEST 2008 WEB-INF/wsdl/
  4390 Thu Jun 05 15:58:48 CEST 2008 WEB-INF/wsdl/SecurityService.wsdl
   641 Wed May 21 12:21:54 CEST 2008 WEB-INF/wsdl/SecurityService_schema1.xsd
  4065 Thu Jun 05 15:58:48 CEST 2008 WEB-INF/wsit-org.jboss.test.ws.jaxws.samples.wsse.ServiceImpl.xml
     0 Wed May 21 12:21:54 CEST 2008 META-INF/services/
    55 Wed May 21 12:21:54 CEST 2008 META-INF/services/com.sun.xml.xwss.RealmAuthenticator
     0 Thu Jun 05 15:58:50 CEST 2008 WEB-INF/classes/META-INF/
  3079 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/META-INF/server-keystore.jks
  1628 Wed May 21 12:21:54 CEST 2008 WEB-INF/classes/META-INF/server-truststore.jks
   581 Thu Jun 05 15:58:48 CEST 2008 WEB-INF/web.xml

On client side, instead, the only required descriptor is the wsit-client.xml file, plus keystore/trustore files.

Check that JBossWS-Metro is installed on your current JBoss Application Server, deploy and test your WS-Security-enabled application.

 

Further information

Samples

The JBossWS-Metro source distribution comes with some samples using X.509 certificate signature and encryption as well as Username Token Profile. You can find them in package org.jboss.test.ws.jaxws.samples.wsse .

 

Username/password configuration

When using the Username Token Profile, the client side configuration is provided through a policy like this:

<wsp:Policy wsu:Id="ClientKeystorePolicy" 
            xmlns:sc="http://schemas.sun.com/2006/03/wss/client">
  <wsp:ExactlyOne>
    <wsp:All>
      <sc:CallbackHandlerConfiguration>
        <sc:CallbackHandler name="usernameHandler" default="kermit"/>
        <sc:CallbackHandler name="passwordHandler" default="thefrog"/>
      </sc:CallbackHandlerConfiguration>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

Whenever specifying username and password in the configuration file is not an option, custom callback handlers may be provided configured through the classname parameter of the Sun proprietary CallbackHandler policy.


Keystores configuration

Keystore and trustore files may be created as usual with keytool. Please inspect the stores provided in the src distribution as samples. The Metro documentation also has a general keystores configuration page which might be useful.

Finally, when providing the keystore/trustore name and location in the wsit-*.xml files, please note that they'll be loaded as resources scanning the META-INF directory in your package (WEB-INF/classes/META-INF when using war packages on JBoss Application Server 5).