users@jersey.java.net

Re: [Jersey] Full-fledged SSL under Jersey

From: Steve Sims <steve_at_steveandgeorge.co.uk>
Date: Sun, 01 Mar 2009 11:05:05 +0000

Hi Gili,

I've only written a test harness (using the pre-Jersey 1.0.2
HttpURLConnection based client not the new Apache based one) to
communicate with my local machine using HTTPS, so I don't known too much
about Java's security mechanisms but basically, Java keeps its trusted
certificates in keyfiles that are modified using the keytool application
supplied with the Java distribution and therefore if you have a trusted
certificate for the server imported, or the certificate's been issued by
a certificate authority whose certificate is in the trust store, then it
should take care of everything for you when you open up a connection.

If you don't have a trusted CA signed (i.e. commercial) certificate then
you can create a keyfile containing your server's key and distribute
that along with the client. I did the following within my test harness:

1) Point firefox towards https://localhost:8081/v1/core/
2) Click Tools->Page Info
3) Click the Security tab
4) Click the View Certificate button
5) Click the Details tab
6) Click the Export button and export the file as a PEM to somewhere
7) Bring up a shell to the place that the PEM file is stored
8) Create a new keyfile: keytool -importcert -alias "localhost" -file
localhost.pem
9) Enter a password for the file such as "adminadmin"

You then need to supply some system properties in order to get the JVM
to load your keystores. Also, if you're testing on the local machine,
because there's no DNS to resolve "localhost", I have to do the
following test only HostnameVerifier hack:

HttpsURLConnection.setDefaultHostnameVerifier(
   new javax.net.ssl.HostnameVerifier() {

   public boolean verify(String hostname, SSLSession sslSession) {
     if (hostname.equals("localhost")) {
       return true;
     }
     return false;
   }
});

System.setProperty("javax.net.ssl.keyStore", <generated keystore filename>);
System.setProperty("javax.net.ssl.keyStorePassword", "adminadmin");
System.setProperty("javax.net.ssl.trustStore", <generated keystore
filename>);
System.setProperty("javax.net.ssl.trustStorePassword", "adminadmin");

There are ways to programmatically update the default keystore however
using classes such as java.security.KeyStore etc.

It helps, whilst trying to get it working to turn on the debug as well:

System.setProperty("javax.net.debug", "ssl,handshake,record");

Anyway, there's lots of information here that will explain things better
than I have - there's just a lot to it! :

http://java.sun.com/javase/6/docs/technotes/guides/security/jsse/JSSERefGuide.html

As far as the username and password issue goes, are you talking about
HTTP BASIC authentication? If so, the new Apache based Jersey client is
probably the way to go, see
https://jersey.dev.java.net/servlets/ReadMsg?list=users&msgNo=4165

Hope this helps a little, it's quite a big area and took me a while to
just get something working - then as soon as I had it I moved on!

Steve

Gili wrote:
> Hi,
>
> What is the best way to communicate over SSL using Jersey? I expect the
> client to:
>
> 1) Request and verify the server certificate
> 2) Encrypt and send the data to the server
>
> I have the following questions:
>
> - How do I request the server certificate (assuming it is found in a CA)?
> - How do I verify it?
> - How do I configure an event listener to prompt me for a user name and
> password when it's needed?
> - Do I need a commercial SSL certificate? Do I lose anything by hard-coding
> my public key into the client? Granted I'll need to issue new clients if the
> server key changes, but is there anything else?
>
> Thank you,
> Gili