Securing Web Services with WebLogic Server 9.2

by Gary Ng and Matt Silver
06/05/2007

Abstract

Web services are becoming more and more important in today's IT landscape, especially with the rapid growth and adoption of Service Oriented Architecture (SOA). By default, Web service invocations (requests and responses) are transmitted in plain text over a protocol such as HTTP. While this allows for a wider range of client interoperability, using plain text transmission incurs security risks. This article discusses some of these security risks and how to avoid them using BEA WebLogic Server's Web service security implementation.

This article is composed of two main parts. The first part is an overview of message integrity, message confidentiality, and authentication, and a brief discussion of how they can be enabled via policy annotations. The second part is a tutorial that takes the reader through an example of building a basic service, and then adding message integrity, message confidentiality, and authority in a step-by-step manner.

It is assumed that the reader is familiar with basic Web service development in BEA WebLogic Server 9.2 and basic security concepts such as digital signatures and encryption.

Web Services and Security Overview

This section provides an overview of the many aspects of Web service security, including message integrity, confidentiality, and authentication. If you are familiar with this material, you can jump to the tutorial.

Web services basics

A basic Web service is composed of two components:

  • The Service Provider—The actual service, being served up by a service container.
  • The Service Consumer—The client that invokes the service. It can be local or remote.


For the purposes of this article, we will assume that the service provider is a Java-based Web service deployed (and running) on a WebLogic Server 9 instance. The service consumer will be a Java client running in its own JVM, on a local or remote computer.

A Web service interaction begins by the client obtaining a WSDL file from the service provider. The WSDL file contains service and invocation information that the client can use to call the service. Once the client has the WSDL file, it can invoke a Web service by sending a plain-text SOAP request message (containing information such as the service to invoke and any parameters) to the provider. The provider receives the message, parses it, and then processes it. Once processing is complete, the provider returns a plain-text SOAP response message (containing any result data) to the client.

We can see from this that plain-text SOAP is the default transmission protocol. This protocol is, unfortunately, highly susceptible to all manner of security attacks. Enter WS-Security to the rescue.

WS-Security

WS-Security, which is defined and maintained by OASIS, outlines three key areas of security that need to be addressed by Web services. Specifically, when request and response messages are exchanged, the following need to be considered:

  1. Message integrity
  2. Message confidentiality
  3. Authentication

Message integrity ensures that a message came from a unique party, and that the message has not been tampered with in transmission. This is achieved by signing the outgoing SOAP message. Signing typically involves attaching a digital certificate (a chunk of encrypted plain text) that represents a unique hash of the message. When the receiving party receives the message, it can compare the contents of the message with the hash; if they match, then the message has not been tampered with in transmission.

Message confidentiality ensures that a message being transmitted can be understood only by the receiving party. This is achieved by encrypting the outgoing SOAP message.

Authentication ensures that an invocation of a Web service is allowed only for authenticated clients. This is achieved by having the client add a WS-Security token (for example, username/password, X.509 certification, Kerberos ticket) to the service invocation. This token is then authenticated by the server's security system at request time, and only if authentication is valid will the service proceed to process the request.

On its own, the default SOAP specification has none of these abilities. While it is possible to manually (programmatically) add support for these features, doing so would be time-consuming and error-prone. Fortunately, the WS-Security spec describes an implementation for these by leveraging the inherent extensibility of SOAP headers. With very little coding, a Web service message exchange can add integrity, confidentiality, and authentication.

Configuring Security in WebLogic Server 9.2 Overview

WebLogic Server 9.2 fully supports the WS-Security standard. This means that by making some small changes to the way the Web service provider and client code are written, message integrity, confidentiality, and authentication can be enabled.

The WebLogic Server API makes it quite easy to enable security; the basic steps for enabling all three security facets are:

  1. Code and test the service without security.
  2. For integrity and confidentiality, set up a keystore for the client and server.
  3. Add security to the service by annotating the source code for the service.
  4. Build and deploy the secured service.

A keystore is essentially a collection of certificates that uniquely and securely identifies the server. Keystores can be created using the keystore command-line tool that ships with the JDK. A keystore can be imported into WebLogic Server using the WebLogic Server admnistration console.

The three facets can be used in any combination (for example, it is possible to just enable integrity, or to enable integrity as well as confidentiality, or all three). This article will demonstrate how to enable each facet.

Policy and Security Overview

Web service security is maintained in WebLogic Server 9.2 through the use of policy files. A policy file is an XML file that dictates how WebLogic Server will attempt to enable various security facets. A Web service is packaged with the policy files, and those policy files are embedded within the service's generated WSDL file at deployment time. When a client attempts to invoke the service, it should first obtain the service's WSDL file along with the policy information.

BEA policy files

WebLogic Server security uses three policy files.

  1. Sign.xml - Needed if message integrity is desired, this file contains configuration information to dicate how message signing takes place between client and server.
  2. Encrypt.xml - Needed if message confidentiality is desired, this file contains configuration information to dicate how encryption takes place between client and server.
  3. Auth.xml - Needed if authentication is desired, this file contains configuration information to decide how to authenticate a client and/or server.

Again, these policy files must be packaged with the Web service at deployment time. Naturally, only the policy file for the required security facet will be required (for example, if only message confidentiality is required, then only Encrypt.xml needs to be packaged; the other two can be ignored).

Creating WS-Policy files

An issue of concern, then, is how to create these policy files. The documentation and schema for these policy files is available from BEA, and they can be written by hand using any text editor. The good news, however, is that these policy files can be automatically generated for you. Annotating the source code appropriately and running the jwsc Ant task will generate the required sign.xml/encrypt.xml/auth.xml files as needed. These autogenerated files will then be automatically packaged in with the deployable Web service.

For the most part, these autogenerated policy files will suffice. Their contents will reflect the annotations that were placed in the original source; as a developer securing a Web service, the only concern you have, then, is making sure you annotate the source code properly. There is no need for a developer to be concerned with creating the policy files.

Having said that, there may occasionally be a situation where the autogenerated policy files will not be usable. Some extra customization of the security framework may be required. An example of this would be a requirement to selectively encrypt only parts of a message instead of the entire body; by default, the autogenerated policy would encrypt the entire message. In this case, the developer is free to hand-create a policy file, and then annotate the source code to use that hand-created policy file. This will prevent autogeneration from taking place. This situation, however, is not usually required as the autogenerated policies are quite adequate (and require much less effort).

Security annotations

Recall that the development of a typical Web service involves coding a Java component (like a POJO or an EJB) and then annotating the code to produce a Java Web Service (JWS). To enable security for a service, the @Policies and the @Policy annotations are added to the JWS.

For example, you can add the following annotation to a JWS:

@Policies({

  @Policy(uri="policy:Sign.xml"),

  @Policy(uri="policy:Encrypt.xml"),

  @Policy(uri="policy:Auth.xml")

})



Using these annotations signifies that the Web service requires all three facets: integrity, confidentiality, and authority. Naturally, each annotation has several optional attributes that can be added. We will examine these later in the article.

Now that we have covered the basics, let's jump into an example of how to create a Web service and add various security facets to it.

Message-level Security Tutorial

In this tutorial, we will create a simple "Hello World"-type service, and then add security facets to it. Our Web service container will be WebLogic Server, and our development environment will be the free, open-source WTP IDE. The entire process will be composed of the following basic steps:

  1. Configure the WebLogic Server environment
  2. Configure WTP
  3. Activate the TCP/IP monitor
  4. Build, generate, and deploy a simple Hello World service
  5. Build a simple client for the Hello World service, and test it
  6. Generate a client key
  7. Import the client certificate into the server's trust
  8. Add integrity to the service
  9. Add confidentiality to the service
  10. Add authentication to the service


Some of these steps (for example, configuring the WebLogic Server environment) are not the focus of this article and will not be discussed in great detail here; see related BEA documentation for more information on how to achieve these steps.

Configure the WebLogic Server environment

Install if it is not already installed. Use the BEA Configuration Wizard to create a new WebLogic Domain with admin username being weblogic and password being password. No special setup (for example, clusters, managed servers, JDBC, JMS) is required, so those stages can be skipped. Call the domain WSTestDomain and leave it in its default directory. This will create the domain directory. If you are using a Windows-based operating system, the domain directory will be something like C:\bea\user_projects\domains\WSTestDomain. We will refer to this directory as DOMAIN_DIR for the duration of this tutorial.

Configure WTP

For the purposes of this tutorial, we will use the widely available and open-source Eclipse IDE, using the Web Tools Platform (WTP) plug-in. If you do not already have it, it can be downloaded from http://download.eclipse.org/webtools/downloads/. Note that this tutorial assumes that the reader is familiar with WTP/Eclipse. If the reader is not, we suggest the reader consult the Eclipse WTP help documentation.

The use of WTP here is arbitrary. Any IDE will suffice (or failing that, a command-line and text-editor-based environment, although a text-based environment will not allow you to examine message traffic—an extra tool facilitating this would be required). WTP was selected for this article simply because it is widely available and open-source (that is, free to download and use) and because it supports a TCP/IP monitor feature that will allow us to see the actual secured messages being transmitted.

Installing WTP typically involves obtaining a ZIP file containing the product and then unzipping it to your file system. When you have done this, launch it. When prompted, select a new workspace directory (for example, C:\workspaces). We will refer to this workspace directory as WORKSPACE_DIR for the duration of this tutorial.

Once WTP is started, you will need to change its default JVM to the JVM shipped with WebLogic Server. Switch to the Java perspective (unless it is already the active perspective). From the menu, select Window | Preferences. In the left pane expand Java and select Installed JREs underneath it. We need to add the BEA supplied JDK. In the right pane, click Add.... Click the Browse... button, navigate to your BEA JDK home directory (typically C:\bea\jdk150_04), and click OK. Both JREs should now be listed. Check the box for the newly added JRE (jdk150_04), and click OK. If a prompt appears asking you to rebuild, then click Yes.

WTP has now been configured, and we can go on to activate the monitor.

Activate the TCP/IP monitor

To test that security is working as desired, we will activate the TCP/IP Monitor feature of WTP. This will allow us to intercept and examine messages being exchanged between client and service. To do that, we have to define a server instance pointing to our WebLogic Server from inside WTP. First of all, stop any currently running WebLogic Server instance (using stopWebLogic.cmd script).

In WTP, open the Servers view. Right-click anywhere on it, and select New | Server. In the pop-up that appears, expand BEA Systems, and select Generic BEA WebLogic Server v9.2. Click Next. In the JRE drop-down menu, select jdk150_04, and then click Next.

Change the Domain Directory to point at DOMAIN_DIR. Change the Start Script and Stop Script fields to point at the corresponding start/stop scripts in DOMAIN_DIR/bin ( startWebLogic.cmd script and stopWebLogic.cmd ). Change the Password to password, and then click Finish. Back in the servers view, right-click on the newly listed Generic BEA WebLogic Server v9.2, and select Monitoring | Properties. In the pop-up Monitoring Ports window that appears, click Add.... In the pop-up menu that appears after that, simply click OK. You should now see a new monitor port (on 7001/7002) listed. Select it and click Start. Click OK.

At this point, any traffic sent to port 7002 will be passed to the monitor, which will display it for us before forwarding it to the (correct) server port 7001. This will let us examine incoming and outgoing traffic.

Build, generate, and deploy a simple Hello World service

We will now create a basic Web service JWS. It will be a very simple service. Simply passed a String, it will return an appropriate greeting. We will then build and deploy the service.

In WTP, create a new Java project called WSTest. In that project, create a new Java class called com.test.HelloWorldService.

We now need to add the BEA weblogic.jar library to the project so our code will compile properly. Right-click on the WSTest project, and select Properties. The Properties window appears. Click Java Build Path in the left pane. Click Libraries in the right pane. Click Add External JARs. In the JAR Selection window that appears, navigate to your WebLogic Server library folder and select weblogic.jar (typically something like C:\bea\weblogic92\server\lib\weblogic.jar). Click Open. You should now see weblogic.jar listed as one of the Libraries. Click OK.

Set the source of HelloWorldService.java to the following:

package com.test;



import javax.jws.*;

@WebService(name = "HelloWorldPortType", 

                serviceName = "HelloWorldService", 

                targetNamespace = "http://mycompany.com")

public class HelloWorldService {



        public String sayHello(String name) {

                return "Hello there, " + name;

        }



}

Note the use of the @WebService annotation, which defines this class as a Web service. Also, note the one business method, sayHello, which takes as an argument a single String, and returns an appropriate greeting.

The next step is to create an Ant script that will build and then deploy the service. Create a text file in the project directory ( WORKSPACE_DIR/WSTest) called build.xml, and set its content to the following:

<project default="build">

<taskdef name="jwsc"

         classname="weblogic.wsee.tools.anttasks.JwscTask" />  

<target name="jwsc">

    <jwsc

      srcdir="."

      destdir="."

      >

      <jws file="com/test/HelloWorldService.java" />

    </jwsc>

  </target>

 <target name="build" depends="jwsc">

        <wldeploy action="deploy"

          name="HelloWorldService"

          source="com/test/HelloWorldService.war" 

          user="weblogic"

          password="password" 

          adminurl="t3://localhost:7001/"

          targets="AdminServer"/>

 </target>

</project>

Nothing very interesting is going on here. Two targets are defined—one that builds the actual service, and one that deploys it.

We can now run the service. Start the admin server in the WSTestDomain. (This can be done from the Servers view inside WTP by right-clicking on Generic BEA WebLogic Server v9.2, and then clicking Start.) Open a command shell window and execute the setDomainEnv script located in DOMAIN_DIR/bin. Then, in the same command shell window, cd to WORKSPACE_DIR/WSTest. From there, run the command ant.

The script should run, and you should see a BUILD SUCCESSFUL message. Do not close the command shell as it will be needed again. At this point, the service should be built, deployed, and running. Open a browser and browse to http://localhost:7001/HelloWorldService/HelloWorldService?WSDL. The WSDL file for the service should be visible. Bookmark this page, as we will need it throughout this tutorial to generate the client proxy. For now, use the browser to save this page as HelloWorldService.wsdl in the WORKSPACE_DIR/WSTest directory (make sure that a ".xml" extension is not added to the end of the WSDL filename).

Pages: 1, 2, 3

Next Page »