Thursday, May 6, 2010

WebService|mutual way ssl certificate with coding and installation

Using JAX-WS-Based Web Services with SSL E-mail
User Rating: / 23 
PoorBest 

This Tech Tip reprinted with permission by java.sun.com

In Java EE 5, a web service that is based on JAX-WS can be implemented either as an EJB endpoint or servlet endpoint. An example of a JAX-WS-based web service implemented as an EJB endpoint is provided in the Tech Tip Developing Web Services Using EJB 3.0. A JAX-WS-based web service implemented as a servlet endpoint is provided in the Tech Tip Developing Web Services Using JAX-WS.

Irrespective of the way a web service is implemented, most enterprise applications, including those that use web services, need to run in asecure environment. Transport Layer Security (TLS)/Secure Sockets Layer (SSL) is a point-to-point secure transport mechanism that can be used for authentication, message integrity, and confidentiality. TLS/SSL (or in this tip, simply "SSL") meets the security requirements of most enterprise application environments, and is widely adopted.

This Tech Tip shows you how to construct a JAX-WS-based web service that runs with SSL, and how to access the web service from an application client. A sample package accompanies the Tech Tip. It demonstrates a Java client accessing a JAX-WS web service using SSL. Examples are provided for web services implemented as EJB and servlet endpoints. The sample uses an open source reference implementation of Java EE 5 called GlassFish. You can download GlassFish from the GlassFish Community Downloads page.

Write the Class for the Web Service Endpoint

Let's begin by writing a Java class for the web service. SSL has no impact on the Java code for the web service endpoint. The same code works for web services that use SSL or that don't use SSL.

In Java EE 5, you can use annotations to easily construct a JAX-WS web service. Here's an example of a web service implemented as an EJB endpoint:

   package ejbws;

   import javax.annotation.Resource;
   import javax.ejb.Stateless;
   import javax.jws.WebService;
   import javax.xml.ws.WebServiceContext;

   @Stateless
   @WebService
   public class HelloEjb {
       @Resource WebServiceContext wsContext;

       public String hello(String msg) {
           return "Ejb WS: " + wsContext.getUserPrincipal() 
           ": " + msg;
       }
   }

The @Stateless annotation marks the class as a stateless session bean, and the @WebService annotation marks the class as a web service. The @Resource annotation is used to declare resource dependencies that the class has -- in essence, what resources the class needs. These resources are then injected into the endpoint implementation. In this example, the annotation identifies a resource dependency on the WebServiceContext. The class needs the WebServiceContext to get context information about requests, such as related security information.

Here's the same web service implemented as a servlet endpoint:

   package servletws;

   import javax.annotation.Resource;
   import javax.jws.WebService;
   import javax.xml.ws.WebServiceContext;

   @WebService
   public class HelloServlet {
       @Resource WebServiceContext wsContext;

       public String hello(String msg) {
           return "Servlet WS: " + wsContext.getUserPrincipal() 
           ": " + msg;
       }
   }

Specify Security Information in Deployment Descriptors

To use SSL in a web service that is implemented as an EJB endpoint, you need to specify security information in a vendor-specific deployment descriptor (in this tip, sun-ejb-jar.xml). For a web service implemented as a servlet, you need to specify the security information in the web.xml descriptor.

One important aspect of secure communication through SSL is server authentication, that is, confirming the identity of the server to the client. Another aspect is client authentication, where the server confirms the identity of the client. In SSL, you can have either server authentication or the combination of server and client authentication (but not client authentication alone). This tip uses the term "mutual authentication" to mean the combination of server and client authentication. (Note however that other documents might attach a different meaning to mutual authentication. For example, in some documents, the term client authentication is synonymous with mutual authentication.)

To enable SSL server authentication, you need to set the <transport-guarantee> element to CONFIDENTIAL. For a web service implemented as an EJB endpoint, you set the element in the sun-ejb-jar.xml deployment descriptor. For a web service implemented as a servlet, you set the element in the web.xml deployment descriptor. As an example, for the HelloEjb web service, the <transport-guarantee> element in the sun-ejb-jar.xml deployment descriptor should look this:

   <ejb>
     <ejb-name>HelloEjb</ejb-name>
     <webservice-endpoint>
       <port-component-name>HelloEjb</port-component-name>
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </webservice-endpoint>
   </ejb>

For the HelloServletService service, the <transport-guarantee> element web.xml deployment descriptor should look like this:

   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Secure Area</web-resource-name>
       <url-pattern>/HelloServletService/HelloServlet
       </url-pattern>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       <role-name>EMPLOYEE</role-name>
     </auth-constraint>
     <user-data-constraint>
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </user-data-constraint>
   </security-constraint>

Notice the <http-method> element value of POST in web.xml. JSR-109, "Implementing Enterprise Web Services", specifies that the service endpoint authorization must be defined using an http-method element value of POST.

In GlassFish, WSDL files are protected by SSL for endpoints with SSL or SSL mutual authentication. For SSL mutual authentication, you need to set the <auth-method> subelement of the <login-config> element to CLIENT-CERT. You also need to set the <transport-guarantee> element to CONFIDENTIAL. For instance, in sun-ejb-jar.xml;

   <ejb>
     <ejb-name>HelloEjb</ejb-name>
     <webservice-endpoint>
       <port-component-name>HelloEjb</port-component-name>
       <login-config>
         <auth-method>CLIENT-CERT</auth-method>
         <realm>certificate</realm>
       </login-config>
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </webservice-endpoint>
  </ejb>

   <security-constraint>
     <web-resource-collection>
       <web-resource-name>Secure Area</web-resource-name>
       <url-pattern>/HelloServletService/HelloServlet
       </url-pattern>
       <http-method>POST</http-method>
     </web-resource-collection>
     <auth-constraint>
       </role-name>EMPLOYEE</role-name>
     </auth-constraint>
     <user-data-constraint>
       <transport-guarantee>CONFIDENTIAL</transport-guarantee>
     </user-data-constraint>
   </security-constraint>
   <login-config>
     <auth-method>CLIENT-CERT</auth-method>
     <realm-name>certificate</realm-name>
   </login-config>

No deployment descriptor is needed for the client program.

Package and Deploy the Web Service Application

Packaging and deploying a web service application that uses SSL is the same as for a web service application that doesn't use SSL. Keep in mind however, that if the web service is implemented as a servlet endpoint in an enterprise archive (that is, a .ear file), you need to include the application.xml file to specify the context-root for the web application.

Write the Client

After deploying the web service, you can access it from a client program. The client program for a web service application that uses SSL is essentially the same as one that doesn't use SSL. The major difference is that instead of using HTTP as the internet protocol, you need to use HTTPS. In the client, you use the @WebServiceRef annotation to declare a reference to a web service. The value of the wsdlLocation parameter in @WebServiceRef is a URL that points to the location of the WSDL file for the service being referenced. So for a web service client that uses SSL, the wsdlLocation parameter in the @WebServiceRef annotation needs to specify an HTTPS URL. For example:

   @WebServiceRef(wsdlLocation=        "https://serverName:8181/HelloEjbService/HelloEjb?WSDL")    private static HelloEjbService helloEjbService; 

You can then access the port for the web service and invoke the web service:

    HelloEjb helloEjbPort = helloEjbService.getHelloEjbPort();    helloEjbPort.hello("Hello World"); 

Client-side artifacts are generated by accessing the WSDL file through HTTPS. To do that, you need to specify the location of a truststore file for the server and its password in the environment variable VMARGS. In SSL, you can use certificates to authenticate the server or for mutual authentication of both the server and client. The truststore file for the server contains the trusted certificates for the server and its keys.

You can specify the location of the server's truststore file and its password in various ways, for example, you can specify them in an ant script as follows:

   <exec executable="wsimport">
     <env key="VMARGS" 
         value="-Djavax.net.ssl.trustStore=${truststore.location} 
         -Djavax.net.ssl.trustStorePassword=${ssl.password}"/>
    <arg line="-keep -d ${client.build} 
    https://serverName:8181/HelloEjbService/HelloEjb?WSDL"/>
   </exec>

Set Up the Client Truststore and Keystore

In addition to a truststore file for the server, you also need a truststore file for the client. The client validates the server certificate against a set of certificates in its truststore. For a secure connection to be made using SSL, the client-side truststore needs to trust the server certificate. For SSL mutual authentication, the server-side truststore also needs to trust the client certificate. If you modify the server-side truststore, you need to restart the server (this allows use of the new certificate). You might not need to do this in a production environment because production certificates are signed by a common Certificate Authority (CA). The GlassFish builds include certificates for several common root CAs.

For SSL mutual authentication, you need to provide your own key in a client keystore (a file that contains the client's keys and certificates). You can use keytool, a key and certificate management utility in JDK 5.0, to generate the keystore.

Run the Client

Before you run the client that access a web service with SSL, you need to set the value of the environment variable, VMARGS. After that, you can run the application as usual. For SSL, set the value of VMARGS to:

   -Djavax.net.ssl.trustStore=${truststore.location}     -Djavax.net.ssl.trustStorePassword=${ssl.password} 

For SSL mutual authentication, set the value of VMARGS to:

   -Djavax.net.ssl.trustStore=${truststore.location}     -Djavax.net.ssl.trustStorePassword=${ssl.password}     -Djavax.net.ssl.keyStore =${keystore.location}     -Djavax.net.ssl.keyStorePassword=${ssl.password} 

Running the Sample Code

To install and run the sample code that accompanies this tip:

  1. If you haven't already done so, download GlassFish from the GlassFish Community Downloads Page, and install it.
  2. Set the following environment variables:
    •  GLASSFISH_HOME. This should point to where you installed GlassFish.
    • ANT_HOME. This should point to where ant is installed. Ant is included in the GlassFish bundle that you downloaded. (In Windows, it's in the lib\ant subdirectory.)
    • JAVA_HOME. This should point to the location of JDK 5.0 on your system.

    Add $JAVA_HOME/bin, $ANT_HOME/bin, and $GLASSFISH_HOME/bin to your PATH environment variable.

  3. Download the sample package and extract its contents. You should now see the newly extracted directory as <sample_install_dir>/ttmay2006ws-ssl, where <sample_install_dir> is the directory in which you installed the sample package. The ws-ssl directory below ttmay2006ws-ssl contains the source files and other support files for the sample.
  4. Change to the ws-ssl directory and edit the build.properties file as appropriate. For example, if the admin host is remote, change the value of admin.host from the default localhost to the appropriate remote host. Also, make sure that the following properties are correctly specified:
    •  server.cert.cn. The CN name of the server certificate. It should be the host name or the fully-qualified domain name. In the default installation of GlassFish, the server certificate has the alias name s1as. You can display the CN by issuing the following command:
    •                     keytool -list -v -alias s1as -keystore                      $GLASSFISH_HOME/domains/domain1/config/cacerts.jks 

      In response, you'll be prompted for a keystore password. Respond with the default password, changeit. You can change the password.

    • admin.user. The ID of the administrator who starts and stops the domain.
    • admin.port. The http port number of administrative server.
    • https.port. The https port number of server.
  5. Update the value of AS_ADMIN_PASSWORD in the passwd file to the administrator password.
  6. Set up the client key and certificate, by entering the following command:
  7.             ant setup 

    This creates a private key in a local keystore, exports the certificate, and imports it to the common truststore. Note that a self-signed certificate is installed in the truststore. This is for testing purposes only and is not recommended for production.

  8. If GlassFish is running, stop it as follows:
  9.             $GLASSFISH_HOME/bin/asadmin stop-domain domain1 

    Then start it:

                        $GLASSFISH_HOME/bin/asadmin start-domain domain1 

    This picks up the new certificate in the truststore.

  10. Build and deploy the sample. First enter the following command:
  11.             ant build 

    This compiles the EJB and Servlet Web Services classes and creates an ear file.

    Then enter the command:

                ant deploy 

    This deploys the ear file in GlassFish.

    And finally, the following command:

                ant build-client 

    This generates artifacts and compiles the client-side code.

  12. Run the client application to access the web service with SSL. Enter the following command:
  13.             ant run 

    You should see results that look something like this:

                [exec] Retrieving port from the service              ejbws.HelloEjbService@4e21db             [exec] Invoking hello operation on the              HelloEjbService port             [exec] Ejb WS: CN=serverName, OU=SSLClient, O=EJTechTips,              L=Santa Clara, ST=California, C=US: Hello World             [exec] Retrieving port from the service              servletws.HelloServletService@ea7549             [exec] Invoking hello operation on the              HelloServletService port             [exec] Servlet WS: CN=serverName, OU=SSLClient,              O=EJTechTips, L=Santa Clara, ST=California,              C=US: Hello World 

    You can see additional information, such as information about the SSL handshake, by adding jvm option -Djavax.net.debug=ssl,handshake. You can do this for the sample by entering the following command:

                 ant run-debug 

    You can verify that this is an SSL mutual authentication by looking at the CertificateRequest during handshake.

    If you want to see more debugging information, use the jvm option -Djavax.net.debug=all.

  14. You can undeploy the Web Service ear file, by entering the command:
  15.              ant undeploy 
  16. After you undeploy the application, remove the generated client certificate from the keystores and restart the server so that the certificate is removed from memory. To do that, enter the commands:
  17.              ant unsetup              $GLASSFISH_HOME/bin/asadmin stop-domain domain1              $GLASSFISH_HOME/bin/asadmin start-domain domain1   

About the Author

Shing Wai Chan is a senior member of the Sun Java Application Server and Java EE SDK development teams. He has been focusing on development projects that relate to security, annotations, CMP, B2B and B2C.

Copyright (c) 2004-2005 Sun Microsystems, Inc.
All Rights Reserved.


2 comments:

suvatha said...

It's nice information...I got the SSL certificate here http://www.xnynz.com/ It provides hosting,domain name register, domain appraisal, online file folder, ssl certificate etc...

Anonymous said...

With many not understanding the impact Java has on SSL Certificates and encryption this holds some valuable information. My SSL provider SSL247.co.uk also provided me with the technical support and assistance I needed for this. But this is a great complimentary piece so thanks for posting!