Java web services: The high cost of (WS-)Security

See how WS-Security overhead stacks up against SSL, and learn when it's worth the cost

WS-Security offers powerful features for securing web service applications, and for many applications these features are essential. But these features come at a high cost in terms of performance and message overhead. Dennis Sosnoski continues his Java web services column series with a look at how using WS-Security or WS-SecureConversation affects Axis2 performance, and he discusses when the simpler (and better performing) alternative of HTTPS-secured connections is a more appropriate choice.

Dennis Sosnoski, Consultant and Trainer, Sosnoski Software Solutions, Inc.

Author photoDennis Sosnoski is a consultant and trainer specializing in Java-based XML and Web services. His professional software development experience spans more than 30 years, with the last 10 focused on server-side XML and Java technologies. Dennis is the lead developer of the open source JiBX XML Data Binding framework and the associated JiBX/WS Web services framework, as well as a committer on the Apache Axis2 Web services framework. He was also one of the Expert Group members for the JAX-WS 2.0 and JAXB 2.0 specifications. The material for the Java Web Services series is based on Dennis' training classes.



07 July 2009

Also available in Chinese Russian Japanese Spanish

Develop skills on this topic

This content is part of a progressive knowledge path for advancing your skills. See Implementing WS-Security for Java web services

WS-Security provides a comprehensive set of security features for Web service applications, building on established industry standards for cryptography and XML encryption and signing. You can specify the features to be used for a particular application with WS-Policy and WS-SecurityPolicy, allowing clients of the service to configure themselves automatically to access the service. With widespread support for these standards across multiple platforms and web services frameworks, interoperability is good (and getting better over time).

Despite these benefits, WS-Security also has some drawbacks. You've seen in the last two articles of this series that WS-Security can be complex to configure, and that it sometimes adds a lot of bulk to the messages being exchanged. So when are the benefits of WS-Security worth the costs? In this article you'll get a better look at the run-time costs of WS-Security and the related WS-SecureConversation (in terms of both processing overhead and added bulk), leading up to a discussion of how to apply WS-Security in a manner that makes sense for your application.

About this series

Web services are a crucial part of Java™ technology's role in enterprise computing. In this series of articles, XML and web services consultant Dennis Sosnoski covers the major frameworks and technologies that are important to Java developers using web services. Follow the series to stay informed of the latest developments in the field and aware of how you can use them to aid your programming projects.

Looking at performance

To measure application performance in different configurations, this article takes the approach of timing the execution of a particular sequence of requests when both the client and the server run on a single system. This approach has some drawbacks — most significantly, it combines client and server processing overhead, making it impossible to evaluate them separately — but offers the advantage of generally yielding more consistent results than running tests over a network. It's also easy to try the tests on your own hardware and JVM, which you can do using the supplied code (see Download).

Performance test application

The application used for testing is a seismic data retrieval service. It's based on an actual database of more than 93,000 earthquakes that occurred worldwide over a period of years. Requests to the service specify query ranges for latitude, longitude, date, or magnitude, and the service returns all matching earthquakes grouped by region and in date order. The entire database is kept in memory and indexed for fast processing of requests, so almost all the processing time for each request is spent in the actual web services processing code (including the data-binding code that converts to and from XML).

Listing 1 shows a sample request to the service, followed by the response (reformatted to fit the page width):

Listing 1. Sample request and response
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns1:matchQuakes xmlns:ns1="http://ws.sosnoski.com/seismic/types">
      <ns1:min-date>2001-08-08T16:31:05.752+00:00</ns1:min-date>
      <ns1:max-date>2001-08-14T23:51:31.499+00:00</ns1:max-date>
      <ns1:min-long>160.4685</ns1:min-long>
      <ns1:max-long>178.19693</ns1:max-long>
      <ns1:min-lat>-42.423557</ns1:min-lat>
      <ns1:max-lat>-30.44976</ns1:max-lat>
    </ns1:matchQuakes>
  </soapenv:Body>
</soapenv:Envelope>

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <ns1:results xmlns:ns1="http://ws.sosnoski.com/seismic/types" count="9">
      <ns1:result-set>
        <ns1:area-name>New Zealand Region</ns1:area-name>
        <ns1:regions count="0">
          <ns1:region ident="rgn159" index="159">NORTH ISLAND,
              NEW ZEALAND</ns1:region>
          <ns1:region ident="rgn160" index="160">OFF E. COAST OF N. ISLAND,
              N.Z.</ns1:region>
        </ns1:regions>
        <ns1:quakes count="9">
          <ns1:quake time="2001-08-11T09:52:54.000+00:00" millis="1000"
              latitude="-37.6499" longitude="177.74" depth="83.0" magnitude="4.4"
              method="ML" region="rgn160"/>
          <ns1:quake time="2001-08-11T09:52:55.000+00:00" millis="0"
              latitude="-37.71" longitude="177.77" depth="70.0" magnitude="4.5"
              method="ML" region="rgn160"/>
          <ns1:quake time="2001-08-11T15:02:47.000+00:00" millis="5600"
              latitude="-38.0429" longitude="175.632" depth="299.8" magnitude="4.6"
              method="ML" region="rgn159"/>
          <ns1:quake time="2001-08-12T07:42:41.000+00:00" millis="7000"
              latitude="-37.97" longitude="175.97" depth="289.0" magnitude="4.3"
              method="MB" region="rgn159"/>
          <ns1:quake time="2001-08-12T22:37:58.000+00:00" millis="5600"
              latitude="-38.3839" longitude="176.121" depth="163.2" magnitude="4.0"
              method="ML" region="rgn159"/>
          <ns1:quake time="2001-08-12T23:25:09.000+00:00" millis="6700"
              latitude="-39.9559" longitude="176.115" depth="76.0" magnitude="4.0"
              method="ML" region="rgn159"/>
          <ns1:quake time="2001-08-13T05:10:07.000+00:00" millis="4300"
              latitude="-37.5859" longitude="176.651" depth="189.0" magnitude="4.3"
              method="ML" region="rgn159"/>
          <ns1:quake time="2001-08-14T02:43:18.000+00:00" millis="2900"
              latitude="-38.3699" longitude="175.902" depth="193.4" magnitude="4.5"
              method="ML" region="rgn159"/>
          <ns1:quake time="2001-08-14T18:02:35.000+00:00" millis="5400"
              latitude="-37.8159" longitude="176.375" depth="193.3" magnitude="4.5"
              method="ML" region="rgn159"/>
        </ns1:quakes>
      </ns1:result-set>
    </ns1:results>
  </soapenv:Body>
</soapenv:Envelope>

In testing, the client generates a pseudo-random series of requests with the query ranges adjusted to cover some portion of the total set of earthquakes. The same sequence of requests is generated each time the client is run with the same input parameters, allowing testing of different Web service configurations. By changing the input parameters to the client (which in turn change the query ranges used for requests), it's possible to test different result message sizes easily.

WS-Security performance

The test results shown in this article are based on two sequences of requests. The first sequence uses 1,000 requests, with query parameters adjusted so each query matches only a small portion of the entire earthquake database (returning only 816 matching earthquakes for the 1,000 requests). The second set uses 100 requests, adjusted to match a larger portion of the database (returning 176,745 matching earthquakes for the 100 requests). Each request sequence was run multiple times in different security configurations, with only the best time for each configuration kept in the results.

The tests were run on a Mandriva 2009.1 64-bit Linux® system with an Athlon X2 5400+ processor and 4GB of RAM, using a Sun Java 1.6.0_13 32-bit JVM. The server code was run on Tomcat 6.0.20, configured to use 1,024MB of heap, with the client code using 512MB of heap. Axis2 version 1.5 was used, with a current build of the Rampart code. (As of the time of the tests, no actual release of Rampart matching the Axis2 1.5 code was available.) The 1,024MB of heap on Tomcat was surprisingly necessary for running the full set of tests (which used a separate Web service application for each security configuration); when initially testing with 256MB of heap, the WS-Security tests sometimes failed with either odd errors that made no sense (for example, "SOAP message MUST NOT contain a Document Type Declaration(DTD)" when no DTD was present) or java.lang.OutOfMemoryError.

The tests were run using each of the following security configurations:

  • plain : No security
  • ssl : HTTPS used for connection to server
  • username : WS-Security plain-text UsernameToken on requests
  • sign : WS-Security signing of body and headers, with timestamp
  • encr : WS-Security encryption of body
  • signencr : WS-Security signing of body and headers, with timestamp and encryption of body

The actual test times ranged from 4 seconds for the plain configuration to 55 seconds for the signencr configuration. Figure 1 shows the relative test times, normalized to multiples of the plain configuration times for easier comparison:

Figure 1. Test time comparison
Test time comparison

As you can see from Figure 1, Secure Sockets Layer (SSL) — technically now Transport Layer Security (TLS) but referred to in this article using the older abbreviation for familiarity — encryption provides close to the same performance as the unsecured case (though it does better in the case of larger messages than for smaller ones, taking about 80 percent longer for the small-messages case versus 20 percent longer for the larger messages). Using WS-Security, on the other hand, causes some huge drops in performance. Just adding simple UsernameToken headers on the request messages causes performance to drop to about the same level as SSL for the small-messages case, and several times slower than SSL for the large-messages case. In the case of combined signing and encryption, the test time is more than 2,100 percent longer than the unsecured case.

Part of this performance hit from WS-Security is due to a flaw in the Rampart handler implementation, which causes it to convert each request and response message to Document Object Model (DOM) form any time Rampart is engaged (even if no security processing is to be done for the message). This particular issue should be fixed in time for a Rampart 1.5 release to go along with Axis2 1.5. Depending on how the fix is implemented, it may substantially improve the times for the UsernameToken test. But even a fix to this issue will probably not affect the other WS-Security times.

The rest of the WS-Security performance hit is due to a combination of how XML Signature and XML Encryption operate, and to the libraries used for the implementations of WS-Security and these XML standards. You may remember from "Axis2 WS-Security signing and encryption" that signing XML messages requires a step called canonicalization, which converts the XML to a particular canonical form before a signature value is computed. The standard requires this step because the decision was made to preserve signatures even after the XML is taken apart by a parser and regenerated. Although this is certainly a useful characteristic of XML Signature, it adds a lot of overhead to the processing. Partly because canonicalization is most easily implemented using a DOM model, the XML security libraries are all written to work with DOM representations of XML. (This is why the Rampart handlers currently generate a DOM if they're even engaged on a service or client, on the assumption that the DOM will be needed anyway.) Just the step of converting data into a DOM representation causes much of the WS-Security overhead, as you can see from the UsernameToken times. In the case of the large response messages, this overhead appears to be about on a par with the actual signature or encryption processing (seen in Figure 1 by comparing the red bar for the username case — where the creation of the DOM is the only major overhead — to those for the sign and encr cases, where actual cryptographical processing is done after the DOM is created).

Beyond the DOM issue, much of the WS-Security overhead is the computationally intensive work of generating digests and encrypting data. This part of the work is required regardless of the implementation method used, so there's a limit to how much improvement can be made to WS-Security processing times. Future articles in this series will compare the performance of some other WS-Security implementations with Axis2/Rampart — but most of these use the same underlying libraries, so don't expect to see any big differences.

WS-SecureConversation

WS-SecureConversation is a standard that builds on the WS-Security and WS-Trust standards to support secure exchanges involving multiple messages. Because it uses a context for an ongoing message exchange, WS-SecureConversation is potentially more efficient than WS-Security. The Rampart distribution includes a separate module called rahas, which enables issuing security tokens required by WS-SecureConversation. It also includes an example (samples/policy/sample04) of a policy configuration using WS-SecureConversation, which was the basis for a policy used with the performance test application.

The WS-SecureConversation policy (not shown here but present in the download as secureconversation-policy-client.xml) includes an <sp:SecureConversationToken> element that details what type of security token will be used for the message exchange and gives the security options to be applied to the token-exchange messages. These token-exchange messages piggyback on the regular message exchange between the client and the service, using operations implemented by the rahas module — so when WS-SecureConversation is in use, you'll see occasional request-response message pairs going between the client and the server, as shown in Listing 2. These added token-exchange messages can be distinguished from application messages both by their use of different security options, as configured by the policy, and by their use of the special http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT request and http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT response action codes, both of which are defined by WS-SecureConversation.

Listing 2. Sample request and response
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
  <soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
    <wsse:Security xmlns:wsse="http://...-wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      ...
    </wsse:Security>
    <wsa:To
    >http://localhost:8800/axis2/services/seismic-secureconversation</wsa:To>
    <wsa:ReplyTo>
      <wsa:Address
      >http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:Address>
    </wsa:ReplyTo>
    <wsa:MessageID>urn:uuid:5EA8E8F04EBA73255B1246409570148</wsa:MessageID>
    <wsa:Action>http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT</wsa:Action>
  </soapenv:Header>
  <soapenv:Body xmlns:wsu="http://...-wss-wssecurity-utility-1.0.xsd"
      wsu:Id="Id-30222347">
    <xenc:EncryptedData ...>
      ...
    </xenc:EncryptedData>
  </soapenv:Body>
</soapenv:Envelope>

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing">
    <wsse:Security xmlns:wsse="http://...-wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      ...
    </wsse:Security>
    <wsa:To
    >http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous</wsa:To>
    <wsa:MessageID>urn:uuid:1BCDE6BE423F5FDE791246409571325</wsa:MessageID>
    <wsa:Action
    >http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/SCT</wsa:Action>
    <wsa:RelatesTo>urn:uuid:5EA8E8F04EBA73255B1246409570148</wsa:RelatesTo>
  </soapenv:Header>
  <soapenv:Body xmlns:wsu="http://...-wss-wssecurity-utility-1.0.xsd"
      wsu:Id="Id-5148380">
    <xenc:EncryptedData ...>
      ...
    </xenc:EncryptedData>
  </soapenv:Body>
</soapenv:Envelope>

For comparing performance with regular WS-Security using certificates, the WS-SecureConversation configuration was set up to use the session token only for encrypting message bodies. Figure 2 shows how the resulting test times compare with the plain and encr test configurations, again normalized to multiples of the plain configuration times for easier comparison:

Figure 2. WS-SecureConversation time comparison
WS-SecureConversation time comparison

As you can see in Figure 2, WS-SecureConversation encryption does provide a significant performance improvement over WS-Security. This is especially true in the case of smaller messages, for which the WS-SecureConversation configuration was almost twice as fast as WS-Security encryption using certificates. The performance advantage is much less pronounced in the case of larger messages, but WS-SecureConversation is still a respectable 18 percent faster in that case.

Message size comparisons

As you've seen in prior articles in this series, WS-Security can add a lot of bulk to SOAP message headers. This added bulk can have a significant effect on performance when the data is sent between client and server over a network (unlike in the performance tests run for this article, where the client and server were running on the same system). The quality of the network connection between the client and the server determines how much impact this added size has on performance, but clearly the larger the messages, the more slowly they are exchanged.

Figure 3 shows the actual sizes of representative messages in the different test cases, again normalized to multiples of the plain configuration results for easier comparison:

Figure 3. Message size comparison
Message size comparison

As you would expect to see, the username configuration adds only to the request message size, because the UsernameToken is only present in the request messages. The other security configurations all add to both request and response message sizes. The bulk added by WS-Security is more significant for the smaller request and response messages, again as you'd expect. The size of the WS-Security headers is basically a constant for each configuration, so that constant size increase has a much more dramatic effect when the original message size is small. When encryption is used, a separate padding effect occurs from the base64 encoding used for the encrypted data.


When to use WS-Security

Now that you've seen the effect of WS-Security on both processing time and message size, you might be wondering when it's worth the cost. The short answer is: when the simpler alternative of SSL won't work. In the rest of this section, you'll get some guidelines to help you determine whether your needs can be covered by SSL or require the full-strength solution of WS-Security, and you'll also get some pointers on minimizing the overhead involved when you do use WS-Security.

Keeping secrets safe

Preserving confidentiality is one of the most important aspects of security. WS-Security uses XML Encryption to keep message content secret from all but the intended recipient, generally by building on public keys wrapped in digital certificates. Encryption can be applied to the entire message or to selected portions, and you can even use multiple layers of encryption to control what information will be accessible to each participant in a message exchange involving multiple systems.

An example use case for WS-Security is an online purchasing system in which the client connects to a merchant system to place an order, but the payment (for example, by credit card) needs to be confirmed by a banking system before the order is processed. If the merchant system has access to the credit card information in unencrypted form, it creates the kind of security risk that has been endemic with browser-based shopping sites: credit card numbers often end up stored in poorly secured databases vulnerable to hackers. Using WS-Security, the credit card information can instead be sent in encrypted form that can be decrypted only by the banking system that issues the payment confirmation.

But for many applications, WS-Security and XML Encryption are overkill when it comes to preserving confidentiality. If your service is contacted directly by clients (rather than indirectly, through other servers) and performs all the necessary processing directly, you can just use SSL (HTTPS) connections for access to provide excellent confidentiality guarantees at a much lower performance cost than WS-Security. This approach only works with direct client connections, though. Otherwise, if the service needs to pass information on to other services, you're back to the same situation as the vulnerable online shopping Web sites, where you use a secured connection to pass your credit card information to the shopping site but there's no guarantee the information will be kept secure by the site server.

Maintaining data integrity

Data integrity is a similar issue to confidentiality. WS-Security uses XML Signature to ensure that data has not been tampered with in transit, because any tampering would invalidate the signature. As with XML Encryption, signing can be applied to the entire message or to selected portions, and you can use multiple layers of signing to guarantee the integrity of data processed by participant in a message exchange involving multiple systems.

The hypothetical online purchasing system also provides a good example for data integrity. Using WS-Security, the client could sign the payment instructions to be sent to the banking system, preventing any modification to the intended payment amount by the merchant-system intermediary. Because the payment amount is signed by the client, it would not need to be encrypted, allowing the merchant system to confirm that the payment amount is correct before submitting it to the banking system.

Here again, WS-Security and XML Signature can be overkill if your service is contacted directly by clients and performs all the necessary processing internally. SSL connections not only keep the data confidential, they also prevent modification of the data in transit — but only between a single client and server. If the server passes data on to other systems, those systems have no guarantee that the data was not modified by the server.

Guaranteeing authenticity

Authenticity is an area in which WS-Security provides features that SSL can't match, even for a direct connection between client and server. Using WS-Security and XML Signature to sign a message gives you a document that not only can be verified as authentic at the time it's received and processed, but also can be stored for audit purposes with the guarantee of authenticity intact.

The best SSL can do on this front is to require client certificates as proof of identity when establishing the connection between the client and server. This provides a much weaker guarantee of authenticity than the digital signing of messages, though. You can't easily store the entire stream of data exchanged between client and server as part of a SSL connection, so even if you verify the client certificate when establishing that connection, there's no way to go back later and prove that this step was correctly handled.

Returning again to the online purchasing system example, the client signature on a payment instruction would allow that instruction to be kept by the banking system and provided if there is later any dispute over the transaction. This would allow the banking system to prove that the payment had been authorized by the client, and thereby isolate itself from any liability.

Beyond the basics

Beyond the basics of confidentiality, integrity, and authenticity, WS-Security provides many other features for specialized security requirements. UsernameToken, for example, is a simple feature providing a standardized way of communicating basic user authentication to a service. Other WS-Security features allow Security Assertion Markup Language (SAML) authorization tokens and other forms of security-related information to be added in to SOAP message exchanges. If you need to use security information of this type in your web services, you'll probably want to use WS-Security support for transporting the information because it defines standard formats and procedures that are likely to be more robust than those you could implement on your own.

Cutting the cost of WS-Security

If you are going to use WS-Security, you can see from this article's test results that performance may be an issue. Before you panic, though, stop to consider the data volume for your service. Cutting the performance of a service by a factor of 22 when using WS-Security for both encryption and signing is a frightening prospect — but if your service is exchanging only a few messages an hour, the difference will be insignificant in terms of hardware demands.

In cases where performance is a valid concern, you can help minimize the performance hit from WS-Security by intelligent use of your security options. Certain web services frameworks tend to generate "all of the above" security configurations, with messages fully signed and encrypted using WS-Security and sent over SSL connections. That's fine if you really want maximum protection and don't care about performance, but in most cases it makes more sense to use either SSL (if you're only concerned about protecting the information in transit between the client and a single server) or WS-Security encryption (if you need to ship data across multiple servers while preserving confidentiality when going through the intermediaries).

You can also use WS-SecureConversation for long-running exchanges of messages between clients and a server (even one accessed through intermediaries), for a relatively modest but significant performance gain as compared to WS-Security using certificates. WS-SecureConversation works especially well in exchanges of relatively small messages where the added overhead of certificates and asymmetric encryption can be large in comparison to the actual (symmetric) encryption of the message body.

Another way of cutting the performance cost of WS-Security is to offload the security processing onto specialized hardware. Some XML gateway appliances provide accelerated processing of WS-Security encryption and signatures. You can use these appliances to handle the heavy-duty WS-Security processing while working with plain SOAP in your application. You obviously need to make sure you don't open any potential security holes in adding an appliance to your server. And you should test the performance gains from the appliance before you purchase. But at least in theory, this type of arrangement can offer some real performance gains.


Wrapping up

The performance cost of WS-Security can be substantial, and there are times when simple SSL point-to-point encryption can be a better solution. But for many types of applications, SSL is inadequate. In these cases, WS-Security (or its offspring, WS-SecureConversation) is required, and the performance cost is simply a necessary expense. In this article, you've read about the costs of WS-Security and learned some guidelines to help you decide whether WS-Security is appropriate for your application.

In the next article of this series, you'll get one more look at WS-Security, this time demonstrating the use of WS-SecurityPolicy for granular control over WS-Security features used by individual operations within a Web service application. Controlling WS-Security at the operation level is yet another technique that can (at least potentially) reduce the overhead of WS-Security, so it makes a great follow-up to this article before the series moves on to other topics.


Download

DescriptionNameSize
Source code for this articlej-jws6.zip1.6MB

Resources

Learn

Get products and technologies

Discuss

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your profile (name, country/region, and company) is displayed to the public and will accompany any content you post. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into Java technology on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=Java technology, SOA and web services, Open source
ArticleID=407176
ArticleTitle=Java web services: The high cost of (WS-)Security
publish-date=07072009