Implementing WS-Security with Java and WSS4J
Many organizations have now implemented solutions based on the promise of Web services, exposing those services over the Internet to enjoy maximum exposure—which then leaves them with the dilemma of securing their services to protect data and other resources. Find out how to use Java and Apache's Web Services Security for Java (WSS4J) framework to secure your Web services.
by Jeff Hanson
|
![]() Web services produce loosely-coupled systems that clients typically communicate with in a stateless, asynchronous manner, requiring no concern for the underlying protocol or location of the service. Unfortunately, this loosely-coupled, open communication environment is rife with potential security threats, as the next section illustrates. Web Services Security Threats Traditional security technologies are not sufficient for Web services security because of the need to secure data and components on a more granular scale. Because Web services use message-based technologies for complex transactions across multiple domains, traditional security processes fall short. A Web-service message can traverse several intermediaries before it reaches its final destination. Therefore, the need for sophisticated message-level security becomes a high priority and is not addressed by existing security technologies. The following list illustrates some of the specific Web-services security threats:
Introduction to WS-Security The WS-Security standard specifies extensions to SOAP messaging that provide message-level integrity, confidentiality, and authentication. WS-Security enables collaboration between other Web services security standards and protocols. Because WS-Security does not dictate one specific security technology, the WS-Security specification allows organizations to use heterogeneous security models and encryption technologies, as well as a number of different security tokens. The WS-Security specification is concerned with three main area of focus:
Validating Authentication Claims using Security Tokens WS-Security uses security tokens to validate authentication assertions made by principals. These assertions are referred to as claims. Claims can be validated by a message recipient or by an authorized third party, such as a certificate authority. You can use two types of security tokens:
WS-Security addresses message integrity (preventing unauthorized message content modification) through XML signatures. You can use signatures to:
WS-Security maintains message confidentiality using XML Encryption in association with security tokens to ensure that sensitive parts of a SOAP message remain confidential. In the rest of this article, you'll see how to create these security tokens, add XML signatures, and add XML encryption to your SOAP messages so that they meet the WS-Security specifications. |
Keystores and the Java Keytool Utility Because the WS-Security specification depends on the use of encryption keys and certificates, it's useful to discuss a mechanism to generate and maintain them. You can use the Java keytool utility, which ships with the JDK, to generate public/private key-pairs and certificates and maintain them in a password-protected keystore so that your Java programs can use them. A keystore is a standard, password-protected repository, also known as PKCS#12, which you can use to store and transport keys and certificates securely. Creating a Keystore and Key-Pair The keytool utility can generate a key pair. Typically, you must generate two key-pairs to use one as a certificate/public-key for the other; therefore, execute the keytool with the -genkey option twice, and store each distinct key-pair into a separate keystore. Here's how to use the keytool utility to generate a key-pair as a private key.
To generate a key-pair to use as a certificate/public-key, use this code (again, enter the entire command on a single line). The preceding commands
Now, look at the pubcert certificate keystore: To examine a key in detail, you can use the keytool utility to display it to the console in RFC 1421 format using the -rfc option, as follows: You'll see output on the console similar to the following: |
Self-Signing Certificates Keys are unusable unless they are signed, but you can use the keytool to self-sign them (for testing purposes only), as follows: Now, the certificate can be self-signed, as follows: Exporting Certificates with the Keytool UtilityAfter generating and self-signing the keys/certificates and storing them in the keystores, import each public key into the other key's keystore. This requires two steps: exporting the public key to a certificate file and importing the certificate to the other keystore. To export the public key to a certificate file, use: You should see a response that says: You can also use the keytool utility to display the contents of the certificate file using the -printcert option, as follows: The output will look like: The exported certificate contains the public key and distinguished name given to the certificate (in this case, pubcert).Importing Certificates into Keystores To import a public certificate into the keystore of the private key, issue the command: The output looks like: Answer the following question: Now that the certificate has been imported into the private key's keystore, you can reexamine the contents of the keystore using the keytool utility with the -list option, as follows: After entering your password you'll see the following output: As the preceding examples illustrated, there are now two entries in the private-key's keystore. The first, with the alias testkey, is identified as a key entry. The second entry is the certificate from the certificate file.At this point you have performed sufficient key management tasks to use the private-key keystore to perform WS-Security tasks using the Apache Web Services Security for Java framework. |
Using the WSS4J Framework Apache's WSS4J is a Java implementation of the OASIS Web Services Security (WS-Security) specification. WSS4J is a framework that you can use to sign and verify SOAP messages with WS-Security information. WSS4J uses the Apache Axis and Apache XML-Security projects and is interoperable with JAX-RPC server/clients and .NET server/clients. WSS4J implements Username Token profile V1.0 and X.509 Token Profile V1.0. WSS4J can generate and process the following SOAP Bindings:
The tools in the next sections demonstrate how to use WSS4J to generate XML that conforms to the latest WS-Security specification.Initializing the WSS4J Framework First, you must initialize the WSS4J framework—in this case, to the default values. For example: Next, create a crypto provider. The default factory getInstance()method creates a provider according to the class name specified by the system property org.apache.ws.security.crypto.provider. If the provider property is not set, the getInstance() method creates a default class instance, org.apache.ws.security.components.crypto.BouncyCastle.The provider is initialized to the values specified in the crypto.properties file found in the WSS4J .jar file. As shipped, that file specifies org.apache.ws.security.components.crypto.Merlin as the provider class. You use the AxisClient as the context engine for messaging operations. Creating the Target SOAP EnvelopeThe following method creates and returns an Axis message from a SOAP envelope string. The SOAP envelope used in this article and passed to the getAxisMessage method shown above is illustrated as follows: Signing a SOAP MessageThe following method uses the WSSignEnvelope class to sign a SOAP envelope and adds the signature data to the envelope in compliance with WS-Security. The "build" method creates the signed SOAP envelope. It takes a SOAP Envelope as a W3C Document and adds a WSS Signature header to it. The signed elements depend on the signature parts specified by the WSBaseMessage.setParts(java.util.Vector parts) method. By default, it signs the SOAP Body element.The "crypto" parameter is the object that implements access to the keystore and handling of certificates. WSS4J includes a default implementation, org.apache.ws.security.components.crypto.Merlin. Listing 1 shows a signed SOAP envelope as returned from the preceding method.Adding Username Tokens to a SOAP Message Listing 2 shows a WSS4J method that uses the WSEncryptBody class to add username tokens to a SOAP envelope in compliance with WS-Security. The SOAP envelope contained within the Axis message returned from the method shown in Listing 2 will look similar to Listing 3: Encrypting SOAP Messages The following method uses the WSEncryptBody class to encrypt part of a SOAP envelope in compliance with WS-Security. The SOAP envelope contained within the Axis message returned from the preceding method will look like Listing 4.The "main" Method Finally, a main method drives the methods defined above to sign, add username tokens to, and encrypt a SOAP envelope. Although the process may initially seem complex, a method such as the main method shown above simplifies the process considerably, breaking it down neatly into just a few steps: creating a SOAP envelope, and then signing, encrypting, and adding username tokens to it. I urge you to download the sample code for this article and experiment with the process. The WSS4J framework provides the core methods you need to meet the WS-Security specifications.
Jeff Hanson has more than 18 years of experience in the software industry. He has worked as senior engineer for the Windows OpenDoc port and as lead architect for the Route 66 framework at Novell. He is currently Chief Architect for eReinsure, which specializes in providing frameworks and platforms for J2EE-based reinsurance systems. Jeff has also authored numerous articles and books.
|