Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX

By submitting your information, you agree that devx.com may send you DevX offers via email, phone and text message, as well as email offers about other products and services that DevX believes may be of interest to you. DevX will process your information in accordance with the Quinstreet Privacy Policy.


Choose the Right Web Services Security Solution : Page 2

Choosing a web services security solution can be daunting. Here's a guide that examines some of the popular security solutions and assesses each one's strengths and limitations.




Application Security Testing: An Integral Part of DevOps

Applying MLS in a Real World Web Service
To demonstrate MLS, the following example encrypts a sample SOAP/HTTP message. The example web service is a simple calculator service whose interface includes a multiply method that accepts two numbers, and the Java client uses the Xfire and WSS4J frameworks. (I tested the web service by hosting it on WebSphere 6.1, but most application servers support basic SOAP message security so you can host the service on an alternate server.) You can download the sample code here. The ReadMe.html file describes the contents of the download ZIP file.

The calculator service is backed up by an EJB implementation. Of course, you can choose an alternative implementation such as JavaBeans. The following is the EJB interface:

package com.dev.ws.security.ejb; public interface Calculator extends javax.ejb.EJBObject { public float multiply(float a, float b) throws java.rmi.RemoteException; }

The EJB bean simply implements the multiply method as follows:

package com.dev.ws.security.ejb; public class CalculatorBean implements javax.ejb.SessionBean { ... public float multiply(float a, float b){ return a*b; } }

The WSDL for the service is shown below. Note that it uses a standard SOAP/HTTP binding and makes the service endpoint available at the URL http://localhost:9080/WSUTSigEncRouterWeb/services/Calculator at port 9080:

<?xml version="1.0" encoding="UTF-8"?> <wsdl:definitions ...> <wsdl:types> ... <wsdl:portType name="Calculator"> <wsdl:operation name="multiply"> <wsdl:input message="intf:multiplyRequest"name="multiplyRequest"/> <wsdl:output message="intf:multiplyResponse" name="multiplyResponse"/> </wsdl:operation> </wsdl:portType> <wsdl:binding name="CalculatorSoapBinding" type="intf:Calculator"> <wsaw:UsingAddressing wsdl:required="false" xmlns:wsaw="http://www.w3.org/2006/02/addressing/wsdl"/> <wsdlsoap:binding style="document" transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation name="multiply"> <wsdlsoap:operation soapAction="multiply"/> ... </wsdl:operation> </wsdl:binding> <wsdl:service name="CalculatorService"> <wsdl:port binding="intf:CalculatorSoapBinding" name="Calculator"> <wsdlsoap:address location="http://localhost:9080/WSUTSigEncRouterWeb/services/Calculator"/> </wsdl:port> </wsdl:service> </wsdl:definitions>

As an educational exercise, first write the client code to call the web service without security. Use the XFire stub generator to create CalculatorServiceClient from the WSDL. The following code uses the stub to call the web service's multiply method, passing it the parameters 5 and 7:

package com.dev.ws.client.calculator.driver; ... public class WSClientUTSigEnc { // Non-SSL URL public static String UT_ENDPOINT = "http://localhost:9080/WSUTSigEncRouterWeb/services/Calculator"; public static void main(String[] args) throws MalformedURLException { CalculatorServiceClient sc = new CalculatorServiceClient(); Calculator calc = sc.getCalculator(UT_ENDPOINT); float a = 5f; float b = 7f; System.out.println(a + " * " + b + " = " + calc.multiply(a,b)); }

After starting the server and running the client, you can use a TCP/IP monitor at port 9080 to observe the messages that the client sends to the web service. You should observe a SOAP message that looks like this:

<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <soap:Body> <multiply xmlns="http://ejb.security.ws.dev.com"> <a>5.0</a> <b>7.0</b> </multiply> </soap:Body> </soap:Envelope>

The client outputs the expected result after getting the SOAP response:

5.0 * 7.0 = 35.0

The SOAP message above simply includes the method request and has no security headers. To enable encryption at the SOAP message level, both the application server and client must be configured to support XML-Encryption. The client uses a public key from an X509 certificate to encrypt the SOAP message and the server uses the corresponding private key to decrypt it. A pair of public/private keys must be generated with the public key given to the client and the private key to the server. (Refer to the following XFire article for details on how to generate the key pairs. The application server configuration is server specific, so refer to your server's documentation for XML-Encryption instructions. You can find the WebSphere configuration instructions here.)

You use handlers to manipulate client SOAP messages in the XFire framework. Each handler accepts a set of properties that specifies the message security that WSS4J must implement. To perform encryption, you must specify properties for the following:

  • The location of the keystore that contains the client's public key
  • The encryption algorithm
  • The parts of the message to be encrypted

The following is the client encryption code for the calculator service:

protected static void configureEncryption(Properties config) { // Encrypt action config.setProperty(WSHandlerConstants.ACTION, WSHandlerConstants.ENCRYPT); //The property file describes the public key used for encryption config.setProperty(WSHandlerConstants.ENC_PROP_FILE, "com/dev/ws/client/driver/outsecurity_enc.properties"); config.setProperty(WSHandlerConstants.ENCRYPTION_USER, "serveralias"); // The encryption algorithm config.setProperty(WSHandlerConstants.ENC_SYM_ALGO,WSConstants.TRIPLE_DES); // Encryption Key Identifier Types config.setProperty(WSHandlerConstants.ENC_KEY_ID, "SKIKeyIdentifier"); // Encrypt the SOAP body String bodyPart = "{Content}{}Body"; config.setProperty(WSHandlerConstants.ENCRYPTION_PARTS, bodyPart); }

Note that the client keystore configuration is contained in the property file outsecurity_enc.properties. The property file describes the keystore location and credentials as follows:

org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin org.apache.ws.security.crypto.merlin.keystore.type=jks org.apache.ws.security.crypto.merlin.keystore.password=keystorePass org.apache.ws.security.crypto.merlin.alias.password=client344Password org.apache.ws.security.crypto.merlin.keystore.alias=serveralias org.apache.ws.security.crypto.merlin.file=com/dev/ws/client/driver/clientStore.jks

Once both client and server are configured, running the client produces the following SOAP message on the TCP/IP monitor:

<soap:Envelope ...> <soap:Header> <wsse:Security ...> <xenc:EncryptedKey ...> <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" /> <ds:KeyInfo ...> ... </ds:KeyInfo> <xenc:CipherData> <xenc:CipherValue> M+Tp2Q4ZtBJtpT1q7SkOALNnpv57Cgh/4EHV0gHONtUZsYQLIVYYWNdYqIkjb81pgxBFU94WKQK au2BEZbF8rL4KdA9tdfb3McRzCOJDcGl4eDs2FC1Pe1Bj0b2VJ+m4D83EhGSsUEeItp+SZcF0Kw jh5dEcV61Q4cscMZaruSg= </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedKey> <xenc:EncryptedData ...> <xenc:CipherData> <xenc:CipherValue...> P8D3xHloRUSCvMA7gNaezLTtENS2R6oXJ8jByaBKvBl5t4joml2qIo9V2LXsnM3nuYJun2UADKfg... </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </wsse:Security> </soap:Header> <soap:Body> <xenc:EncryptedData ...> <xenc:CipherData ...> <xenc:CipherValue ...> dIxwIHuC9TCLbSmfsgohBr2A81lY+GfPA7lofgXPcMvcblO+hOVeiKMyxXvuZF8M2fEtmHTa3kVY fNDYFAKauoDwq4lWBKMuk4f0s8mTkhyBJrMmbD2mrw== </xenc:CipherValue> </xenc:CipherData> </xenc:EncryptedData> </soap:Body> </soap:Envelope>

The SOAP message is now encrypted and the clear-text body has been replaced by its cipher value. The SOAP header contains encryption method information.

This example demonstrates the extensive configuration that is required to perform encryption using Message Level Security. While MLS has definite advantages over TLS in terms of performance and support for end-to-end security, you must take into account the additional complexity that it entails. For many applications, support for granular and end-to-end message security is not critical, and TLS is an adequate confidentiality and encryption solution.

The next section turns to authentication and examines one of the simplest solutions: UsernameToken Authentication.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date