SummaryBy Pankaj Kumar. Revision: 0.81, Date: Apr. 2, 2002.
This HOWTO guide explains steps involved in (i) deploying SSL accessible Java Web Services in Servlet based SOAP platforms such as Apache Axis or HP Web Services Platform ( HP-WSP ); and (ii) running Java client programs that access these Web Services with https protocol. The guide accompanies scripts and sources for a simple application consisting of a simple Web Service ( Hello World variety ) and a client to illustrate the setup steps.
Introduction
This guide is for you if
Apache Axis is an opensource software and can be downloaded from http://xml.apache.org/axis. Evaluation copy of HP-WSP can be downloaded from http://www.hpmiddleware.com. This guide and the supplied example scripts and sources are based on Apache Axis Alpha3 and March 2002 release of HP-WSP.
A Servlet based SOAP platform is usually not aware of SSL. It is the Servlet container who takes care of all the encryption, decryption and verification stuff. In this respect, use of SSL is transparent to the SOAP platform or the Web Service. So, what is needed is the steps to setup the servlet container for SSL. In addition, the WSDL description of the Web Service must specify the appropriate URL to access the service.
This guide includes the steps for Apache Jakarta Tomcat 4.0.1 and HP-AS 8.0, a full-fledged J2EE AppServer free for commercial use. You can download HP-AS 8.0 from http://www.hpmiddleware.com. It is noteworthy that HP-AS 8.0 supports certificate based client authentication whereas my preliminary investigation on Tomcat 4.0.1 leads me to beleive that Tomcat doesn't support this capability. However, I don't track Tomcat development very closely and I could be wrong here. Let me know if I this is so.
Certain steps mentioned in this guide require the Java source files and scripts available in
the caompanion resource WSOverSSL.zip
.
Download WSOverSSL.zip and unzip it. This would create the directory with name
WSOverSSL
and place the contents within this directory. As the scripts to compile, deploy
and run the client are SOAP Platform specific and there are minot differences in the client source
code as well, I have kept sources for Apache Axis and HP-WSP in separate sub-directories with names
axis
and hpwsp
.
I have written only Windows scripts to compile, deploy and run the examples only. Translation to Linux/Unix scripts are straightforward. A future revision of this document will use OS neutral Apache Jakarta Ant scripts. File and directory pathnames and environment variable used in this guide follow the Windows convention. Again, translation to Linux/Unix names are trivial.
Environment variable JAVA_HOME
is used in all the scripts for easy switch
among different JDKs, either from one or different vendors.
Rest of the guide is organised in following sections:
Install JSSE
You can skip this if you using JDK1.4 or above as JSSE is now part of the JDK.
I tried the steps on my WIndows NT machine with Sun's JDK1.3. It sould work on other OS platforms and JDK1.2.x and 1.3.x with no or minor changes.
Note that you must have JSSE, either as part of JDK1.4 or separately installed, to be able to setup Apache Jakarta TomCat or HP-AS 8.0 for SSL. It is also needed for running the client program.
jsse.jar
, jcert.jar
and jnet.jar
to your
%JAVA_HOME%\jre\lib\ext
directory and editing the
%JAVA_HOME%\jre\lib\security\java.security
file to add the following line:
security.provider.3=com.sun.net.ssl.internal.ssl.Provider
%JAVA_HOME%\lib\ext
, but that didn't work for me. Later on, I
figured that Sun's documentation for JSSE uses JAVA_HOME
to point to jre
sub-directory of JDK installation directory whereas I have used JAVA_HOME to point to
JDK Installation directory itself.
axis
or hpwsp
and
edit the script
testhttps.bat
for your environment. This script invokes the URLReader
program ( part of the download ) to access url https://www.etrade.com
with proper
options to the JVM. If you are behind a corporate firewall, you should edit the script file to
use appropriate values for System properties https.proxyHost
and
https.proxyPort
. Following worked fine for me:
%java_home%\bin\java -Dhttps.proxyHost=web-proxy -Dhttps.proxyPort=8088 \ -Djava.protocol.handler.pkgs=com.sun.net.ssl.internal.www.protocol \ URLReader https://www.etrade.com
Note that character \
is used to indicate line continuation and must not appear in
the actual command.
Pay attention to these System properties and understand their significance. A proper understanding now will save you a lot of grief later on.
If the script testhttps.bat
doesn't work, recheck the steps in Installing JSSE. If
you are not using environment variable %JAVA_HOME%
, you may want to verify that the
right JVM ( the one whose jre\lib
sub-directory has been updated ) is being used.
One way to do this is to display System property java.ext.dirs
. This should have
%JAVA_HOME%\jre\lib\ext
as a component.
CLASSPATH
. Also, you could add the SSL Provider to the
java.lang.Security
class within your program and not specify in the commandline.
Refer to JSSE documentation for more details.
Generate Certificates and KeyStores
In this section, we will use the keytool
utility of JDK to generate keys,
certificates, keystores and truststores. Though you don't need to
understand the underlying concepts for
setting up your system for this example, but if you run into problems or want to modify the setup for
your own specific needs, I would advise going through the references at the end of this guide or any
other source to understand the functioning of keytool
utility and its relationship
to certificates, public and private keys, keystores, truststores and other such topics.
Take a look at the script file genks.bat
:
if not "%JAVA_HOME%" == "" goto gotJavaHome echo You must set JAVA_HOME to point at your Java Development Kit installation goto cleanup :gotJavaHome echo Generating the Server KeyStore in file server.keystore %java_home%\bin\keytool -genkey -alias tomcat-sv \ -dname "CN=localhost, OU=X, O=Y, L=Z, S=XY, C=YZ" \ -keyalg RSA -keypass changeit -storepass changeit -keystore server.keystore echo Exporting the certificate from keystore to an external file server.cer %java_home%\bin\keytool -export -alias tomcat-sv -storepass changeit \ -file server.cer -keystore server.keystore echo Generating the Client KeyStore in file client.keystore %java_home%\bin\keytool -genkey -alias tomcat-cl \ -dname "CN=Client, OU=X, O=Y, L=Z, S=XY, C=YZ" \ -keyalg RSA -keypass changeit -storepass changeit -keystore client.keystore echo Exporting the certificate from keystore to external file client.cer %java_home%\bin\keytool -export -alias tomcat-cl -storepass changeit \ -file client.cer -keystore client.keystore echo Importing Client's certificate into Server's keystore %java_home%\bin\keytool -import -v -trustcacerts -alias tomcat -file \ server.cer -keystore client.keystore -keypass changeit -storepass changeit echo Importing Server's certificate into Client's keystore %java_home%\bin\keytool -import -v -trustcacerts -alias tomcat -file \ client.cer -keystore server.keystore -keypass changeit -storepass changeit :cleanup
Note that the character \
is used to indicate continuation of the same line. You won't
find this in the actual script file.
As the comments indicate, this script creates a self signed cerficate for the server and the client
and stores them in keystores server.keystore
and client.keystore
,
respectively. Also, the server's certificate is exported to file server.cer
and
imported to client's keystore client.keystore
. Similarly, the client's
certificate is exported to file client.cer
and imported to
server's keystore server.keystore
. This way, keystore client.keystore
can also be used by the client as the truststore to verify the cetificate supplied by the server
and vice-versa.
With respect to the script genks.bat
, it is important to note that:
localhost
. If you plan
to access the server with its symbolic name or IP address on the network, you must specify that
string while generating the key. You can also have multiple certificates for the same physical
machine.dname
values.Note that in a typical use of SSL to access a web application, the client authenticates the server
based on the certificate presented but the server rarely authenticates the client based on certificate.
That is how we use https protocol from our browsers most of the time. This works fine as there are
other mechanisms to identify and authenticate the client such as username and password, credit card
no. and the billing address and so on. However, these mechansims will not be availalble to a Web
Services client and hence it makes sense to use certificate based client authentication.
Configure Servlet Container for SSL
Configure Tomcat 4.0.x for SSL
This configuration is really simple. Edit the %TOMCAT_HOME%\conf\server.xml file and uncomment the entry for SSL connector. Also add the attributes for keystore filename and password. Find below the edited entry for my setup:
<!-- Define an SSL HTTP/1.1 Connector on port 8443 --> <Connector className="org.apache.catalina.connector.http.HttpConnector" port="8443" minProcessors="5" maxProcessors="75" enableLookups="true" acceptCount="10" debug="0" scheme="https" secure="true"< <Factory className="org.apache.catalina.net.SSLServerSocketFactory" keystoreFile="c:\progs\java\WSOverSSL\hpwsp\server.keystore" keystorePass="changeit" clientAuth="false" protocol="TLS"/< </Connector>
The bold lines are specific to my setup. You may need to change these values for your setup.
To test the new configuration, restart the container and access the URL
https://localhost:8443
from your browser. It might warn you that the
certificate presented by the server is not recognised. We did not get our certificates signed
by a well-known CA, did we? However, keep pressing 'Yes'
to the questions and eventually you should see the welcome page for Tomcat.
Tomcat 4.0.1 doesn't seem to support client authentication. I did not find any attribute of
element Factory
to specify the truststore and its password. A truststore is needed to
verify the certificate presented by a client. As I have the client's certificate exported to the same
keystore file, I tried just setting the attribute clientAuth
to true
. But
this didn't work.
However, you can supply the truststore and its password as System properties to the JVM running the Tomcat and that would enable client authentication. Though I did not try this myself, a couple of folks have pointed to me that it does work.
We will see in the next section that HP-AS 8.0 supports specification of truststores and SSL
based client authentication.
Configure HP-AS 8.0 for SSL
This section assumes that you have HP-AS 8.0 installed in directory %HPAS_HOME%
. If
you have selected default options while installing HP-AS, its value should be c:\hpmw\hpas
If you don't have HP-AS 8.0, you can get it from
http://www.hpmiddleware.com/.
%HPAS_HOME%\config\hpas
and copy file https-service-config-example.xml
to
https-service-config.xml
. Now edit this file to reflect your setup. Find below the edited
file for my setup:
<listener-service ports="9443" backlog="50" max-request-handlers="20" max-request-contexts="20" max-response-contexts="20" request-handler= "com.hp.mwlabs.as.services.listeners.https.HttpsRequestHandler" container="servlet" socket-timeout="PT0S" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://www.hp.bluestone.com/xml/schemas/listener-service-2_0.xsd"> <server-socket-factory class-name="com.hp.mwlabs.as.services.listeners.JsseSslServerSocketFactory"> <property name="remoteTrustAlgorithm" value="SunX509"/> <property name="keyStorePassword" value="changeit"/> <property name="protocolVersion" value="TLS"/> <property name="keyStoreFile" value="file:///c:/progs/java/WSOverSSL/hpwsp/server.keystore"/> <property name="enableSessionCreation" value="true"/> <!-- rarely will this be false --> <property name="keyType" value="SunX509"/> <property name="keyStoreType" value="JKS"/> <property name="keyPass" value="changeit"/> <property name="requireClientAuth" value="true"/> <property name="useKeyStorePassAsKeyPass" value="false"/> <property name="trustStoreFile" value="file:///c:/progs/java/WSOverSSL/hpwsp/server.keystore"/> <property name="trustStorePassword" value="changeit"/> </server-socket-factory> </listener-service>Lines that changed are in bold. Note that this configuration file requires that the clients also present certificates. Also, in my installation of HP-AS, the original file
https-service-config-example.xml
had XML comments at the end of the file. Delete these
lines. I had to go through tech. support to get this right.hpas-deploy.xml
to
add an entry for HTTPS listener. I added this entry just after the entry for HTTP listener:
<Service name="https" class="com.hp.mwlabs.as.services.listeners.ListenerService"> <Configuration url="https-service-config.xml" reload="30"/> </Service>Note that this entry is very similar to the entry for HTTP.
http://localhost:9443
. It should take you the HPAS 8.0 start page.Running the Example Program
The supplied example demonstrates the use of HTTP over SSL ( or https ) for communication between two Web Service end points. Use of https protects the content exchanged and can also be used by one end point to authenticate the other.
The example consists of a simple Java class Hello
with method
String greet(String anme)
and a client class client.Client
. Class
Hello
is deployed as a Web Service and the client invokes the method
greet()
with the string specified in the command line parameter.
Instructions to run the example program and troubleshooting tips can be found in readme.html file
stored with example
sources and scripts, in sub-directory axis
for Apache Axis example and in sub-directory
hpwsp
for HP-WSP.
Troubleshooting Tips
Here are some generic troubleshooting tips.
setHPWSEnv.bat
file for values reflecting your setup. Check and recheck the spelling of values. Once you have
identified the problem, look at the appropriate resource for troubleshooting tips.Look at the platform specific readme.html for more specific troubleshooting tips.
Known Problems
I have observed following problems during my experimentation. These may be specific to the version of the software I am using.
https.proxyHost
and https.proxyPort
. The exact error message I got was: Unable to tunnel through
web-proxy:8088. Proxy returns "HTTP/1.0 503 Service Unavailable
.
Utility Wsdl2java
retrieved the WSDL file correctly
from https url outside the corporate firewall but the client program failed. This is possible as
Wsdl2java
uses the JDK classes to access the URL whereas Axis has its own implementation
of HTTP over TCP/IP.BindException: Address in use:
connect
. I have never encountered this over HTTP. Also, I didn't observe this on my slower
350MHz Pentium machine, but can reproduce very quickly on faster 900MHz Athlon machine.References
Copyright © 2002, Hewlett-Packard Co.