HTTP-based security mechanisms are now the best way to keep your Web services secure. This article explains how to set up security for a JavaTM Web services client so that it establishes an SSL connection with the server. To authenticate the Web services client, a user ID and password are included as part of the HTTP header of the Web services request. IBM® WebSphere® Application Server uses these credentials to perform authentication against a predefined user registry. SSL is used for encryption of all requests and responses, including the client's user ID and password, and for authentication of the server as well (because the Java client will establish an SSL connection only if it trusts the server that it's connecting to). This article shows you how to set up WebSphere Application Server V5.0, IBM HTTP Server V1.3.26 (hereafter called HTTP Server), and a Web services client for SSL communication and authentication.
The software configuration used in this article is shown in Figure 1:
Figure 1. Configuration of the software components
The Web services client sends its requests to an IBM HTTP Server instance, using an HTTPS (HTTP over SSL) transport protocol. As a result, all communication takes place over a secure SSL link. Messages sent to the HTTP Server and responses received are encrypted, which prevents unauthorized users from seeing any sensitive information exchanged between server and client. The use of SSL is transparent to the SOAP transport of a Web service.
The WebSphere Application Server plug-in, which runs as a module within the HTTP Server, determines that the HTTP request should be redirected to WebSphere Application Server. It receives the request and checks the user ID and password included as part of the HTTP header to authenticate the Web service client. These credentials are verified against information in a user registry to determine if the user is really who he or she claims to be. In our configuration, the user registry is an LDAP server. However, it could be any user registry supported by WebSphere Application Server, including an operating system registry or a custom registry.
The communication links between HTTP Server and WebSphere Application Server, and between WebSphere Application Server and the LDAP server can also be secured by configuring these components to use SSL. We decided not to use SSL past the HTTP Server since we assume that only trusted entities (authorized users) have access to the network. In a real world situation, you should secure the communication paths between these components also. We decided not to cover this subject since the Redbook IBM WebSphere V5.0 Security Handbook explains in detail how to enable SSL between these software products.
Even though this article covers security at the transport layer, it is worth mentioning that a new set of security standards for Web services are being developed. Some of these standards, such as XML encryption and Security Assertion Markup Language (SAML), focus on achieving security at the XML document level instead of using the security solutions built into the channel used for SOAP message transport. The idea behind these standards is that Web services should be transport protocol neutral and should not rely on the security capabilities of that layer.
This article assumes that a Web service and its Java proxy client were created in WebSphere Studio Application Developer V5.0 (hereafter called Application Developer) using the Web services wizard. The Java proxy client should have the following public methods:
- A set end point method for setting the URL address of the Web service to be invoked.
- A proxy method exists for each business method in the Web service implementation that should be visible to clients.
If you used the default options in Application Developer when creating the Java proxy client for your Web service, you should have these methods.
Additional assumptions:
- Global security has been enabled in WebSphere Application Server.
- WebSphere Application Server has been configured to use a user registry to authenticate users.
- The user ID and password that will be used to authenticate the Web service client are valid (the user ID and password exist in the user registry that WebSphere Application Server uses for authentication).
- The Web service was tested prior to setting up security.
Summary of steps to set up security for your Web service
Here are the high level steps to set up an SSL connection between the Web service client and the HTTP Server:
- Install the Java Secure Socket Extension library and configure Application Developer so that Java projects can use this library.
- Test the Java Secure Socket Extension installation and the Application Developer configuration.
- Create a self-signed certificate for the HTTP Server.
- Import the self-signed certificate into the client truststore file.
- Configure security for the HTTP servlet (rpcrouter servlet) that handles the incoming requests for the Web service implementation.
- Modify the Java proxy client generated by the Web services wizard in Application Developer (details below).
- Write a Java program that initializes the JVM environment so that SSL connections can be established. (This Java program is a client object to the Java proxy class we modified in the previous step).
Install the Java Secure Socket Extension packages and configure Application Developer
You can
download the Java Secure Socket Extension (JSSE) library
from the Sun Web site (scroll down to the Downloads section). Extract the contents of the downloaded ZIP file and save all JAR files (
jcert.jar, jnet.jar, jsse.jar
) to a folder in your file system. In Application Developer, create a new classpath variable for each of these JSSE jar files. In Figure 2, the classpath variables
JCERT_JAR, JNET_JAR,
and
JSSE_JAR
are defined, respectively, for each of the JSSE JAR files. You can choose the name when defining these classpath variables. To access the Classpath Variables window, select
Window => Preferences
, expand the Java node in the tree, and then select
Classpath Variables
.
Figure 2. JCERT_JAR, JNET_JAR, and JSSE_JAR classpath variables
Let's add these classpath variables to the Java build path of the project that contains your Web service Java proxy client. Figure 3 shows that the
JCERT_JAR, JNET_JAR,
and
JSSE_JAR
variables were added to the Java build path of the Web services client project. To access the Java Build Path window, right-click on the folder of the Java project, select
Properties
, and select the
Java Build Path node
.
Figure 3. Java build path for the Web services client project
You should now be able to write Java code in Application Developer that uses the classes in the JSSE package to establish SSL connections.
Test the Java Secure Socket Extension installation and the Application Developer configuration
This is a good time to test the work done so far.
Download the ZIP file
at the bottom of this article. It contains a Java class named
SSLTester
that you will use to test your JSSE installation and Application Developer configuration. In Application Developer, import this file into a Java project whose Java build path includes the JSSE JAR files. The Java project that contains your Web service client should be already properly configured, so you might want to import this file into that project.
Since the JSSE package allows a Java client to connect only to trusted servers, use the SSLTester program to connect to a server that has a public certificate trusted by the JSSE package. By default, the JSSE package trusts only servers that have a corresponding certificate entry in the jssecacerts or
cacerts keystore files.
To execute the SSLTester program, pass in, as a run-time argument, the URL of a public server that uses HTTPS for establishing connections. Make sure the public HTTP server you choose for this test has been issued a public certicate by a trusted certificate authority. JSSE will allow a connection to this HTTP server only if it trusts the certificate authority that issued the HTTP server's public certificate. The program will try to connect to the supplied URL and, if successful, will send the HTML returned from the server to the standard output.
To connect to a server that you trust but is not trusted by default by the JSSE package, you can create your own keystore file for the client and add a certificate entry for the server to which you want to connect. This is what we will do in order to connect to the HTTP Server.
Create a self-signed certificate for the HTTP Server
Let's create a self-signed certificate for the HTTP Server to which your Web service client will send HTTP requests. This certificate will be imported into the Web service client's keystore file so that the HTTP Server can authenticate to the client. Remember that JSSE allows Java clients to connect only to entities it trusts.
Once the HTTP Server authenticates to the client, the communication between them is encrypted. The client's user ID and password are transmitted via a secure link to HTTP Server, which then routes the request to WebSphere Application Server.
To create a self-signed certificate for the HTTP Server, you must first create a keystore file to hold that certificate. Start the Key Management Utility that is shipped with HTTP Server (this utility is also known as
ikeyman
) and follow these steps:
- From the menu, select Key Database File => New .
- Select CMS key database file from the Key database type drop-down list.
-
Enter a file name for the new keystore. Use
webServerKeyStore.kdb(see Figure 4). -
Enter a path in the Location text area. Use
C:\IBMHttpServer\certs(see Figure 5). - Click OK .
- Enter and confirm a password.
- Select Stash the password to a file , which allows HTTP Server to use the password to gain access to the certificates contained in the keystore.
- Click OK .
Figure 4. Creating the keystore file for HTTP Server
Figure 5. Setting up the password for access to the keystore file
Now that we have a keystore file, let's generate a self-signed certificate for the HTTP Server:
- From the menu, select Create => New Self-Signed Certificate . A window will open and request information in order to generate the self-signed certificate.
-
Enter a key label for this certificate. Do not use spaces in the key label. We use
HTTP ServerCertificate. - Select X509 V3 as the Version and 1024 as the Key Size
-
The first two fields of the Distinguished Name -- Common Name and Organization -- are required. For Common Name, use the fully qualified machine name where the HTTP Server is running. We use
roliv.austin.ibm.com. Organization Unit, Locality, and State/Province are optional -- we left them blank - Select the appropriate Country.
-
Enter
365as the Validity Period. - Click OK .
Figure 6. Self-signed certificate for HTTP Server
The HTTP Server's self-signed certificate needs to be imported into the client's keystore so that the client can recognize this server as a trusted entity. To import the server's certificate into the client's keystore file, you must first export the certificate out of the server's keystore:
- Select Personal Certificates in the IBM Key Management drop-down list and select the HTTP ServerCertificate that was just created.
- Click on Extract Certificate to extract the certificate to a file:
- Click OK .
- Close the key database and quit the IBM Key Management program.
Figure 7. Personal certificates for HTTP Server
Import the HTTP Server self-signed certificate into the client's keystore
There are two types of entries in a keystore: key entries and trusted certificate entries. A key entry contains an entity's identity and its private key. A trusted certificate entry, on the other hand, contains only a public key in addition to the entity's identity.
A truststore is a keystore that is used to decide what entities should be trusted. When you can verify that you are receiving data from an entity that you trust, then you can assume that the data you are receiving is really coming from that entity. When you add an entry to a truststore, you are making the decision to trust that entity. To add an entry to your truststore, you just need to import the public certificate of an entity.
The keystore we created for the HTTP Server holds a key entry that contains identity information about this server. Now we need to create a truststore for the client and import the server's public certificate into it. We use the keytool program in the JDK to do these tasks (for information on this utility, see the Sun documentation). You can use keytool as follows:
keytool -import -v -trustcacerts -alias <alias_server_name> -file <server_certificate_file> -keystore <client_truststore_file> |
where:
-
alias_server_nameis an alias name of your choice for the HTTP Server -
server_certificate_fileis the file containing the server's public certificate we exported -
client_truststore_fileis the file name of the truststore to generate
In our case, we executed the keytool utility with the following parameters:
keytool -import -v -trustcacerts -alias IHSServer -file webServerPubCert.arm -keystore client.keystore |
Keytool will prompt you for a password to protect your truststore file. Write down this password since it will be used by the Web service client.
Your HTTP Server needs to be configured to use SSL before moving on. The WebSphere Security Redbook is one of several documents that describes in detail how to configure the HTTP Server for SSL support. Here is a brief overview of the required configuration steps. It is assumed that your HTTP Server has not yet been configured in any way except for the addition of the directive that loads the WebSphere Application Server plug-in module. If it has been modified, consult the HTTP Server documentation before making the following changes. In the HTTP Server
conf
directory, you will find the
httpd.conf
file. Open this file with a text editor to add
128-bit SSL support.
On UNIX®, add or uncomment the following lines:
LoadModule ibm_ssl_module libexec/mod_ibm_ssl_128.so AddModule mod_ibm_ssl.c |
On Windows®:
LoadModule ibm_ssl_module modules/IBMModuleSSL128.dll |
Create a VirtualHost entry in the
httpd.conf
file to allow the HTTP Server to respond to requests on more than one address or port number. The IP-based VirtualHost entry below is used to service encrypted HTTPS requests on TCP/IP port 443. The scope of the SSL support is limited by specifying the
SSLEnable
directive within the VirtualHost tags. The
SSLServerCert
directive is not required if you only have a single VirtualHost. This directive can be used to associate a unique SSL sever certificate label with a specific VirtualHost. Since
HTTP ServerCertificate
was the key label we used for the HTTP Server certificate that we created, we'll use that same value for the
SSLServerCert
directive.
Listen 10.1.1.1:443 <VirtualHost 10.1.1.1:443 > ServerName roliv.austin.ibm.com SSLServerCert HTTP ServerCertificate SSLEnable </VirtualHost> |
As a preventive measure to safeguard against SSL being used globally, disable SSL after closing the VirtualHost entry. The SSL timeout values apply to any VirtualHost entries defined for this HTTP Server instance, since they are specified outside the VirtualHost entry. The keystore to use for this server is globally specified as well. The settings used in our example are:
SSLDisable Keyfile C:/IBMHttpServer/certs/webServerKeyStore.kdb SSLV2Timeout 100 SSLV3Timeout 1000 |
After updating and saving the
httpd.conf
file, restart the HTTP Server so that the changes are loaded.
Once your HTTP Server is configured for SSL support, you can test the server and client keystores that you created. A Java program named
IHSServerClient
is included in the companion ZIP file. This program is similar to the
SSLTester
program we used earlier to test the JSSE package. In Application Developer, import this program into the same Java project where you imported
SSLTester.
IHSServerClient
expects three run-time arguments -- the URL of the HTTP Server, the path and filename of the truststore file we created using the keytool utility, and the password for accessing the truststore file. We used
https://roliv.austin.ibm.com
for the first argument (our HTTP Server runs on
roliv.austin.ibm.com
) and
c:\client.keystore
for the second argument. For the password argument, use the password that you entered when the keytool utility prompted you for a password. When you execute
IHSServerClient
, it connects to your HTTP Server instance and sends the HTML it receives to the standard output. If an error occurs, you probably made a mistake when importing the server's public certificate into the client's truststore file, and you can use the debugging capabilities of the JSSE package to determine what is wrong. For more information on how to turn on debugging for the JSSE classes, see the JSSE documentation.
Configure security for the rpcrouter servlet
In Application Developer, a Web project is created when the Web services wizard is used to create a Web service. This Web project contains a servlet named
rpcrouter
, which is responsible for receiving and processing SOAP requests from Web service clients (
rpcrouter
knows where to route the incoming requests). By restricting access to this servlet authenticated users only, we secure access to the Web service implementation. Configuring security for this servlet is no different from securing any other servlet. You can use Application Developer or the Application Assembly tool to modify the deployment descriptor of the Web project so that security is enabled for the
rpcrouter
servlet.
For details on how to secure a servlet, see the WebSphere Application Server Information Center. At a high level, here are the steps to secure the
rpcrouter
servlet:
- Define a security role.
- Define a security constraint.
- Define a Web resource collection.
-
Specify the URL pattern for the
rpcrouterservlet (in our case,/servlet/rpcrouter). -
Specify the HTTP methods to secure for the
rpcrouterservlet (in our case,GETandPOST). - Specify which user roles are authorized to access any Web resource collections within this security constraint (in our case, authenticated users only).
Here is a snapshot taken from WebSphere Application Server of the security configuration for the
rpcrouter
servlet:
Figure 8. Security configuration for the rpcrouter servlet
In order for this security configuration to take effect, make sure that you have enabled global security in WebSphere Application Server and that WebSphere Application Server is using a valid user registry (such as an LDAP server) for authentication and authorization.
Modify the Web service client code
After you have modified the deployment descriptor so that security is set for the
rpcrouter
servlet and you have deployed your Web service, it is time to modify the Java client code. In the companion ZIP file, you will find a Java class named
WebServiceClient
. It initializes the JVM environment so that SSL connections can be established using the JSSE package. In Application Developer, import this class into the same project where you have your Java proxy client. As mentioned earlier, it is assumed that a Java proxy client class was created by the Web services wizard in Application Developer. You'll be making changes to both classes. Start by modifying your proxy client so that it has methods for setting the user ID and password that will be used to access your Web service. We simply added two new instance string variables (
userId
and
password
) and two new methods:
public synchronized void setUserId(String userId)
{ this.userId = userId; }
public synchronized void setPassword(String password) {
this.password = password; }
|
You also need to modify the method that creates the
org.apache.soap.rpc.Call
object (look for the
createCall() method
). We added the lines shown in bold:
Call call = new Call(); soapHTTPConnection.setUserName(userId); |
These two lines add the specified user ID and password to the HTTP header of the request. No more changes are needed to your Java proxy client. Now let's work on the WebServiceClient class. Open this file in Application Developer and make the changes suggested in the included comments:
// Modify the following line so that an instance of the
// corresponding Java proxy client is created
// WebServiceProxy proxy = new WebServiceProxy();
try {
URL url = new URL(serviceURL);
// Uncomment the following lines
//proxy.setEndPoint(url);
//proxy.setUserId(userid);
//proxy.setPassword(password);
// Modify the following method call so that it
//calls the right proxy business method
//proxy.businessMethod();
}
catch(Exception e) {
System.err.println(
"An exception occurred while invoking Web service: " + e.getMessage());
}
|
The
WebServiceClient
program creates an instance of your Java proxy client and initializes it with the URL of the Web service and with a user ID and a password for authentication. It also calls a proxy business method on the Java proxy client (you must change the proxy business method invocation to the right one).
WebServiceClient
takes five run-time arguments:
- URL of the Web service you want to connect to
- File name of the truststore file for your client (the file we created earlier with the keytool utility)
- Password to access the truststore file
- User ID that the client should include in the HTTP header of the request for authenticating against the user registry.
-
Password for above user ID. This user ID and password must fall under the security role that was defined when configuring security for the
rpcrouterservlet.
You should now be able to use this client program to send requests to your Web service.
The security capabilities offered by a transport layer can be effectively used to secure Web services. This article showed you how to provide security to a Web service using HTTP-based security mechanisms (HTTP over SSL). By using SSL to establish connections with the server, you can encrypt all of the information (including the client's user ID and password) exchanged between the Web service Java client and the Web service server. SSL was also used to verify the identity of the server.
| Name | Size | Download method |
|---|---|---|
| client.zip | 3 KB | FTP |
Information about download methods
-
IBM WebSphere V5 Security Handbook
-
IBM WebSphere V5 Web services Handbook
-
HTTP Server (powered by Apache): An Integrated Solution for IBM iSeries Servers
Ricardo Olivieri is a software engineer in IBM Global Services in Austin, Texas. He works on the development team for the Mixed Address Database application (a registration tool for IBM devices). His expertise includes the design and development of enterprise Java applications that run on the WebSphere Application Server, and he is a certified Java developer/programmer and a certified WebSphere Application Server V4 AE administrator. You can reach Ricardo at roliv@us.ibm.com .




