Using JAX-WS Handlers to configure Weblogic Web Services Security

It works ... and this is how ...Read on!

This is a very basic/minimalistic/simple yet successful implementation of Web Services Security (WSS), using OpenSSO, where two handlers are configured, one each on the Web Services Client (WSC) side and the Web Services Provider (WSP) side. It is important to note that this implementation is based on the JAX-WS framework. If you are interested in the JAX-RPC implementation, please take a look at Malla's blog.

THE Advantage of using Handler approach: JAX-WS is an industry standard. Hence, the handlers implemented for one container (For eg. Weblogic) will be re-used for other containers (like - Glassfish, JBoss, Tomcat, WebSphere.)

OpenSSO's Role: OpenSSO provides two services. Authentication of clients which invoke the WS and a Security Token Service (STS) that secures the message sent from the client to the server. In "English" this means that,

  • Every user who accesses the WSC needs to identify her/himself with a valid username and password (Authentication.) OpenSSO is responsible for validating these credentials and allow/deny access to the WSC.
  • Once the user is authenticated, he/she can send a request to the WSP (in this case, send a stock symbol like "JAVA".) This is in the form of a SOAP message and this message also needs to be protected.
  • The client side handler intercepts the SOAP message (request from the client) and invokes OpenSSO's Security Token Service (STS) to secure the request using a Security Token (For eg., SAML Token, UserName Token, X509 Certificate).
  • On the WSP side, the request first hits the server side handler which is in-charge of validating the incoming message. For this, the handler contacts OpenSSO again and  uses the security API to validate the integrity of the message.
  • Once verified, the request is passed on to the service and the response again follows the same path, through the handlers (handler-chain), back to the client's browser.

Implementation Details

The web service in this example is a simple stock quote service where the client sends a stock symbol and requests the server to respond with the current stock value and a few other details. Follow the steps explained below to achieve your own working implementation of web-services secured using JAX-WS handlers and OpenSSO.

Pre-Requisite: You need to have OpenSSO deployed and configured on any one of the supported containers. You also need to install Weblogic 10.3.

Disclaimer: Since, this is a preliminary implementation, some of the configuration details (like, URL of the OpenSSO server and the WSP/WSC profile names) are hard-coded in the code.

Download Resources: Click on the links below to download all the resources you need to get going.

At the Server Side:

This implementation follows the Top-down web-services implementation, i.e., building the WS starting from the WSDL file.

  1. The WSDL file for this WS is the "stockservice.wsdl" and "stock.xsd" is a schema file that has definitions of some other complex types that are used by the web-service.
  2. Most of the work of creating the stubs for the service and client is achieved using the Ant Tasks provided by Weblogic. The "build.xml" has all the tasks/targets defined (but, the hard-coded paths to all the jars need to be modified based on where you have downloaded them). You can find a detailed Ant Task Reference here. Also, take a look at this link to understand the process of creating JAX-WS web-services from the WSDL file.
  3. Include the jars from the lib.zip in the build path. This folder contains the openssoclientsdk.jar file among others.
  4. The first ant task that we run is the wsdlc task, in the target - "generate-from-wsdl." The wsdlc task takes as input the WSDL file (srcWsdl) and in return produces an Interface file and a stubbed out implementation file for the web-service. These are called the JWS interface and implementation files. Furthermore, the Interface file is added to a jar file that the task creates and puts in the directory/location specified by the destJwsDir attribute, in this case, "generated." The stub of the implementation file is placed in the destImplDir. packageName specifies the package in which the implementation file is created and the most important attribute that needs to be in there is the  type of the web-service. If we forget this one, then, by default a JAX-RPC implementaion is created.

    <target name="generate-from-wsdl">
        <wsdlc
            srcWsdl="stockservice.wsdl"
            destJwsDir="generated"
            destImplDir="generated/impl"
            packageName="com.sun.samples"
            type="JAXWS"/>
      </target>
  5. Take a look at the StockService_StockQuotePortImpl.java (Yes! this is the way wsdlc names the impl file - <name of the service>_<name of the port type>Impl.java) from the downloads (<source files downloaded here>\\source\\StockService\\src\\com\\sun\\samples folder) Fill in your stub (generated above) with the required implementation details from this file.
  6. Take note of the JAX-WS annotations used in the code and especially the one used for including the StockService_handler.xml file (Handler configuration file).
    @HandlerChain( file="StockService_handler.xml" )
  7. Next, we need to build the service using the jwsc ant task. This task builds the service and creates a deployable WAR file for it. This WAR file is placed in the  destdir. The jws element is a direct child of this task and takes as inputs the Impl file (generated and mofdified in Steps 3-4) and the jar file, also generated in Step 3 by the wsdlc task. The <WLHttpTransport> element is used to specify the context path of the web-service.

    <jwsc
          srcdir="src"
          debug="true"
          destdir="dist"
        >           

         <jws file="com/sun/samples/StockService_StockQuotePortImpl.java"
               compiledWsdl="generated/stockservice_wsdl.jar"
                 type="JAXWS">    

                <WLHttpTransport contextPath="StockQuoteService"
                               serviceUri="StockService"
                               portName="StockQuotePort" />
        </jws>    
           <classpath refid="client.class.path"/>
        </jwsc>
  8. In the remaining part of the build.xml, the WAR created in Step 6 is modified by including the libraries (openssoclientsdk.jar and xmlsec.jar) in WEB-INF/lib folder; adding AMConfig.properties from <resources downloaded here>\\wss_resources to WEB-INF/classes and adding the StockService_handler.xml file to the location where all other class files are located.

    A note about the AMConfig.properties file: If you are using the file as downloaded with the WSS Agent from the OpenSSO Agents download page, then you need to make the following changes (copied from Malla's blog) to it:

    com.iplanet.services.debug.level=message    //This helps in debugging for any failures
                com.iplanet.services.debug.directory=<directory where debug files can be written>  // for e.g. /tmp/wss
                com.iplanet.am.naming.url=http:<openssohost>:<openssoport>/<openssodeploydir>/namingservice
                com.sun.identity.agents.app.username=amadmin
                com.iplanet.am.service.password=<password for the amadmin>
                com.encryption.pwd=<No setting i.e. empty, remove if any macro is present here>
                com.iplanet.am.server.protocol=http
               com.iplanet.am.server.host=<host where the OpenSSO is deployed> // for e.g. localhost
               com.iplanet.am.server.port=<port where the OpenSSO is deployed> // for e.g. 7001
               com.iplanet.am.services.deploymentDescriptor=<deployment uri> // for e.g. opensso
               com.iplanet.am.cookie.name=iPlanetDirectoryPro
               com.sun.identity.saml.xmlsig.keystore=<directory where the keystore.jks is localted>
                              // here it is $openssowssagentsdir/resources/keystore.jks
               com.sun.identity.saml.xmlsig.storepass=$openssowssagentsdir/resources/.storepass
              com.sun.identity.saml.xmlsig.keypass=$openssowssagentsdir/resources/.keypass
              com.sun.identity.saml.xmlsig.certalias=test
              com.sun.identity.login.url=http://<openssohost>:<openssoport>/<deployuri>/UI/Login
              com.sun.identity.liberty.authnsvc.url=http://<openssohost>:<openssoport>/<deployurl>/Liberty/authnsvc
              com.sun.identity.wss.trustclient.enablemetro=false  //Will not use the Metro API
  9. Finally, deploy the WAR (or create an EAR using the  build-ear target) in Weblogic. Test the WS deployment by accessing the WSDL at http://<FQDN>:<Weblogic port>/StockService_StockQuotePortImpl/StockService?WSDL (this URL will differ if you modified the service/port names in the WSDL)

At the Client-side:

  1. ClientFilter.java is responsible for re-directing new users to the OpenSSO login page so they can get authenticated and obtain an SSOToken. The OpenSSO login URL is hard-coded in this java file (search for "loginURL".) Modify it before building the client.
  2. ClientHandler.java secures the outgoing SOAP request by enclosing it within a token (SAML, UserName, etc. based on what's selected for the given WSP/WSC profiles in OpenSSO) obtained from the STS.
  3. GetQuote.java is a servlet that calls the exposed public method of the web-service and displays the results for the users.
  4. Include the jars from the lib.zip in the build path and build the client application using the build.xml (beware of the hard-coded paths!) and deploy the resulting WAR file on the Weblogic server.
  5. Access the client at http://<FQDN>:<Weblogic port>/<Client's context root>/index.jsp (You can determine the context root from the Testing tab of the client application on weblogic console) Enter any stock symbol and click on "Get Quote" button.
So... it works. Doesn't it!

PS:

  • Use the fully qualified domain name of your machine when accessing OpenSSO. 
  • If OpenSSO is deployed in Tomcat 6.0.18, you will need to enable cookie encoding as explained in Madan's blog, otherwise you might stumble upon redirect loop issue in firefox.
  • You can choose a preferred security mechanism by logging in to OpenSSO and navigating to Access Control -> Default realm-> Agents -> Web Service Client (and/or Web Service Provider) -> wsc (and/or wsp) -> logout.
  • I implemented this WS on a Windows XP platform.
  • Although most of the references have already been linked to from the above text, here is one for info.on how to create and use SOAP message handlers for JAX-WS on weblogic.
Comments:

Thanks for this example. I am anxious to get it to work.

I am unable to create a war for the StockService with the supplied source for this example to deploy to Weblogic 10.3, because there is no web.xml or weblogic.xml in it. Do you have the sample web.xml and weblogic.xml files you used for Weblogic 10.3? In particular, did you include the agent filter in web.xml to enforce an Access Manager authentication for StockService war?

Posted by Mike Bencoe on October 13, 2009 at 05:20 AM PDT #

Mike,
This article is a little out-of-date.
I would suggest you try following this article - more comprehensive coverage and instructions - http://developers.sun.com/identity/reference/techart/wss_opensso/wss_sdn-1.html (You can obtain web.xml from this article and as far as I remember, I did not modify the weblogic.xml file)

We include a filter on the WSC side (with the StockClient.war). The user is directed to OpenSSO for authentication and then the Subject information is added to a ThreadLocal object which is available at the WSP (StockService) side.

Posted by Kamna Jain on October 13, 2009 at 06:43 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Kamna Jain

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today