Using JAX-WS Handlers to configure Weblogic Web Services Security
By Kamna Jain on Jun 02, 2009
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.
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.
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.
- 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.
- 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.
- Include the jars from the lib.zip in the build path. This folder contains the openssoclientsdk.jar file among others.
- 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.
- 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.
- 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" )
- 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.
- 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.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.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.sun.identity.saml.xmlsig.keystore=<directory where the keystore.jks is localted>
// here it is $openssowssagentsdir/resources/keystore.jks
com.sun.identity.wss.trustclient.enablemetro=false //Will not use the Metro API
- 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:
- 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.
- 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.
- GetQuote.java is a servlet that calls the exposed public method of the web-service and displays the results for the users.
- 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.
- 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.
- 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.