Securing the Web Services Framework
| January 2007 | |
|
Abstract
Web services are often used to integrate with systems external to an organization, which quickly leads security-minded administrators to voice concerns about the plain-text nature of the SOAP protocol. This concern should not to be taken lightly, considering that both authentication credentials and potentially sensitive business data will be transmitted across the public internet.
Since web services are merely resources served up by the application server, they can leverage the same techniques traditionally
applied to servlets, images, static HTML and other web resources:
- Basic authentication - a very simple authentication mechanism between client and server
- Secure Sockets Layer (SSL) - an encrypted communication channel established between client and server
Basic authentication transmits credentials in plaintext, so it is necessary to implement both these measures in order to enhance the
security of the WSF. Note that this security is between the web service producer and consumer, and does not
protect information between the WSF and the Docbase.
This article will offer specific instructions for Tomcat 5 and WebLogic 8.1, although the same principles will
apply to most J2EE application servers.
Table of Contents
Before you Begin
The Web Services Framework Development Guide
is an excellent introduction to developing and deploying web services using the WSF. This article assumes that you have deployed or are
familiar with the services described in the guide, specifically the Hello service.
Additionally, this article also assumes that you have generated the consumer side of this web service using the WSDL2Java
tool provided by the Axis engine. Below is a test program that we will refer back to throughout this article to illustrate how the client
code must change to accomodate the security enhancements.
import com.documentum.ws._2005.framework.*; // DocbaseCredentials
import com.myorg.ws._2005.services.*; // Hello service
import org.apache.axis.message.*; // SOAP Header
public class TestHello {
public static void main(String args[]) throws Exception {
if(args.length<3) {
System.out.println("Usage: docbase user pass");
System.exit(1);
}
String repository = args[0];
String domain = "";
String username = args[1];
String password = args[2];
// get token from Docbase Credentials service
DocbaseCredentialsServiceLocator credentialsLocator = new DocbaseCredentialsServiceLocator();
credentialsLocator.setMaintainSession( true);
DocbaseCredentials credentials = credentialsLocator.getDocbaseCredentials();
DocbaseCredentialsInfo info = new DocbaseCredentialsInfo(
repository, domain, password, username
);
String token = credentials.newCredentials(info, true);
System.out.println("Acquired Token=" + token);
// setup hello service
HelloServiceLocator hloc = new HelloServiceLocator();
hloc.setHelloEndpointAddress("http://localhost:8080/ws/services/Hello");
HelloSoapBindingStub hstub = (HelloSoapBindingStub) hloc.getHello();
// set token header
String namespace = "http://localhost:8080/ws/2005/services";
SOAPHeaderElement header = new org.apache.axis.message.SOAPHeaderElement(
namespace, "DocumentumSecurityToken"
);
header.setPrefix("");
header.setActor(javax.xml.soap.SOAPConstants.URI_SOAP_ACTOR_NEXT);
javax.xml.soap.SOAPElement element = header.addChildElement("token");
element.addTextNode(token);
hstub.setHeader(header);
// call Hello service
System.out.println("Calling Hello service = " + hstub.greet("my test"));
}
}
|
If you are unfamiliar with the client code generated by the WSDL2Java tool, please see my article titled
Consumers of the Web Services Framework for a full description. This client code is pulled directly from the article.
Basic Authentication
The basic authentication scheme is familiar to anyone who browses the internet. It is a very simple authentication method that allows
users to provide credentials to a web page. Most browsers prompt the user for a username/password combination when a web resource
requires this type of authentication.
Using the same technique, application servers can force web service consumers to supply credentials. The application server can enforce
this restriction with only minor configuration changes.
Enable Basic Authentication
To enable basic authentication, open the WEB-INF/web.xml file contained in the web context and add the following lines
right before the ending </web-app> element:
<security-constraint>
<display-name>Security Constraint</display-name>
<web-resource-collection>
<web-resource-name>Protected Area</web-resource-name>
<url-pattern>/*</url-pattern>
<url-pattern>/services/*</url-pattern>
<http-method>DELETE</http-method>
<http-method>GET</http-method>
<http-method>POST</http-method>
<http-method>PUT</http-method>
</web-resource-collection>
<auth-constraint>
<role-name>manager</role-name>
</auth-constraint>
</security-constraint>
<login-config>
<auth-method>BASIC</auth-method>
<realm-name>Example Basic Authentication Area</realm-name>
</login-config>
<security-role>
<description>role required to access ws
</description>
<role-name>manager</role-name>
</security-role>
|
Now you need to define the manager role, which is application server specific.
Defining a Role in Tomcat
If you do not already have a manager role defined in $CATALINA_HOME/conf/tomcat-users.xml, then add the
following line to this file, and restart Tomcat:
<user username="admin" password="adminpass" roles="manager"/>
|
Defining a Role in WebLogic
From the tree navigation of the administration console, click into Security > Realms > myrealm as shown below.

Click on the 'User Management' tab and select 'Manage Users within this Security Realm'. Select 'Configure a new User'' and add a user named 'manager' with an appropriate password.
Testing Basic Authentication
Since the role is now established, you should be prompted by your browser when visiting the following URL.
Modifying the Client Code
Now we need to modify our web service consumer code so that it
passes credentials in the request. Using the client code shown earlier, we must add the following lines for the
DocbaseCredentials and Hello service.
// get token from Docbase Credentials service
DocbaseCredentialsServiceLocator credentialsLocator = new DocbaseCredentialsServiceLocator();
credentialsLocator.setMaintainSession( true);
DocbaseCredentials credentials = credentialsLocator.getDocbaseCredentials();
<b>// added to pass credentials
DocbaseCredentialsSoapBindingStub dcstub = (DocbaseCredentialsSoapBindingStub) credentials;
dcstub.setUsername("admin");
dcstub.setPassword("adminpass");</b>
|
The call to the Hello service already uses the binding stub, so the code change is even simpler.
HelloSoapBindingStub hstub = (HelloSoapBindingStub) hloc.getHello();
<b>hstub.setUsername("admin");
hstub.setPassword("adminpass");</b>
|
The only problem with basic authentication is that it transmits the credentials in plaintext. The username and password are
base 64 encoded, but this is easily deciphered. I will address this issue by showing you how to enable SSL on your application
server in the next section. With an encrypted channel between the web service and consumer, basic authentication is an excellent way to
restrict access to services.
Secure Sockets Layer (SSL)
The most effective way to secure SOAP transmissions is to enable SSL on the WSF application server. SSL guarantees safe
passage of information between client and server, and addresses the "man-in-the-middle" attack that would allow a third
party to interpret the data being exchanged.
In order to assert the identity of a server, an external Certificate Authority (CA) is typically used, but I will
focus on self-signed certificates, which do not require purchasing a certificate. A self-signed certificate
is more than adequate to prove out our SSL solution, and is easily replaced later with one from a global CA like Thawte or
Verisign.
Configuring the Local Keystore
These instructions are taken almost verbatim from the Tomcat documentation,
and I include them within this document so
they are easily referenced. The first step will be the creation of a local certificate keystore. This command can be run
from the command line:
$JAVA_HOME\bin\keytool -genkey -alias tomcat -keyalg RSA
|
The keytool program will prompt you for specific information. Enter the relevant information, with the password 'changeit'.
This password is expected by Tomcat, please do not use another value.
Enter keystore password: <b>changeit</b>
What is your first and last name?
[Unknown]: <b>first last</b>
What is the name of your organizational unit?
[Unknown]: <b>myorgunit</b>
What is the name of your organization?
[Unknown]: <b>myorg</b>
What is the name of your City or Locality?
[Unknown]: <b>mycity</b>
What is the name of your State or Province?
[Unknown]: <b>mystate</b>
What is the two-letter country code for this unit?
[Unknown]: <b>US</b>
Is CN=first last, OU=myorgunit, O=myorg, L=mycity, ST=mystate, C=US correct?
[no]: <b>yes</b>
Enter key password for <tomcat>
(RETURN if same as keystore password):
|
This will create a self-signed certificate in the keystore of your user's home directory, named .keystore.
This is a Java Keystore (JKS) formatted file, which is the Sun default format. The application server will use the information in
this file as its identity.
Enable SSL on Tomcat 5
Go into the $CATALINA_HOME/conf/server.xml file and uncomment the Connector entry that enables SSL.
<Connector port="8443"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" debug="0" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
/>
|
Tomcat will look for the .keystore file in the user's home directory by default, if you need to specify the .keystore file path
then you can add an attribute called keystoreFile to the Connector element.
Enable SSL on WebLogic
In the console navigation, click into Server > myserver.
Then, click the 'General' tab and check the 'SSL Listen Port Enabled' box, along with specifying an 'SSL Listen Port.

Then click the 'Keystores and SSL' tab, click 'Change', and set the Keystore type to 'Custom Identity and Java Standard Trust'.
Then fill in the form shown below. Type in the full path to the keystore file created in the previous step, use 'JKS'
as the key store type, and 'changeit' as the pass phrase throughout.

Testing SSL
After restarting either Tomcat or WebLogic, visit the secure port with your browser to verify that you can manually enter the site.
https://localhost:8443/ws
|
Client Trusted Certificate Authority
When a server sends a certificate, it is the client's responsibility to check the validity of that certificate.
Java clients have a built-in list of certificate authorities (CA), which contains companies like Verisign who are deemed trustworthy.
Verisign then vouches for other organizations who wish to prove their identity.
In our case, we have a self-signed certificate. This means that there is not a CA who can vouch for us, and any Java client that tries
to connect to our server will reject our questionable identity. But we can make the JDK to recognize our self-signed certificate
by running the following command to export the self-signed certificate to a file.
keytool -export -alias tomcat -file tomcat.cert
|
Then import the certificate into the JDK's trusted CA store which is located in $JAVA_HOME/jre/lib/security/cacerts. The command will look like this on
Windows, modify the path accordingly on other operating systems:
keytool 'import 'alias tomcat 'keystore C:\j2sdk1.4.2_03\jre\lib\security\cacerts 'file tomcat.cert
|
You will then be presented with a series of prompts, use 'changeit' as the password and answer yes to 'Trust this certificate?'
Enter keystore password: <b>changeit</b>
Owner: CN=first last, OU=myorgunit, O=myorg, L=mycity, ST=mystate, C=US
Issuer: CN=first last, OU=myorgunit, O=myorg, L=mycity, ST=mystate, C=US
Serial number: 453030b5
Valid from: Fri Oct 13 20:35:01 EDT 2006 until: Thu Jan 11 19:35:01 EST 2007
Certificate fingerprints:
MD5: DD:2D:8A:14:91:60:CA:6C:46:B2:FF:04:21:4F:7D:2F
SHA1: F0:50:03:A7:CE:54:7C:50:4E:2B:29:25:91:68:F8:94:43:54:26:7A
Trust this certificate? [no]: <b>yes</b>
Certificate was added to keystore
|
Now the self-signed certificate is a member of the trusted CA. When we make a connection, the server identity will be accepted by the JRE.
Modifying the Client Code
The last step is to modify the client code to make requests to the secure port of our application server. Again, referring
to the client code provided earlier, set the endpoint address of each service locator to point to the SSL enabled port.
DocbaseCredentialsServiceLocator credentialsLocator = new DocbaseCredentialsServiceLocator();
<b>credentialsLocator.setDocbaseCredentialsEndpointAddress(
"https://localhost:8443/ws/services/DocbaseCredentials");</b>
...
HelloServiceLocator hloc = new HelloServiceLocator();
<b>hloc.setHelloEndpointAddress("https://localhost:8443/ws/services/Hello");</b>
|
Summary
Web services are a powerful tool for both internal and external integration points, but they can also open
up legitimate security concerns. Their communication channel is often over public infrastructure,
which could expose sensitive data and valuable intellectual property.
Using the techniques in this article, you can enhance the security of the WSF and leverage the value additions
already built into your application server.
About the Author
 |
Fabian Lee has over 10 years experience as a software engineer and consultant,
and has been assisting customers with technical and business solutions based on Documentum for over six years. His clients have
included some of the leading names in the airline, finance, insurance, health, government, and IT sectors. Fabian currently works as
a consultant at Flatirons Solutions Corporation, focusing on their government ECM solutions in the Washington, D.C. area.
Fabian started working with the WDK at version 1.0.1, and has written customizations for each major version since. An
avid open-source enthusiast, he works on several community projects including the Repository Interrogation Tool.
|
References
Related Articles
Inside the Web Services Framework, Fabian Lee
Consumers of the Web Services Framework, Fabian Lee
SOAP Libraries and Axis Engine
Axis Home Page
Web Services Security
Tomcat
SSL Configuration HOW-TO
DCTM Technical Publications
WSF Development Guide
|