Java EE and .NET Interoperability: Integration Strategies, Patterns, and Best Practices

Problems

It is not uncommon for developers to embed the security processing logic (such as verifying the access rights of the requester and signing the message) in the application code. Such practice allows easy testing of both business functionality and security requirements, without dependency on external program units that provide security functions. This becomes convenient when building Java EE .NET interoperable applications where each platform has its own security processing requirements. However, when the business application grows larger in scale or becomes highly distributed, the maintenance effort and support to manage a change in the security processing logic is enormous. For example, a change in the message digest algorithm or in the access rights processing logic may require considerable program changes in each application program, recompilation and subsequent retesting.

Handlers are processes that can take the service request from the requester's object and process it. For example, a handler can be customized to digitally sign a SOAP message when a service request is created. Thus there is no need to embed the digital signing processing logic in the service requester's application. In essence, handlers are internal representations of actions when an event is triggered or a service request is received. When applied to Java EE .NET interoperability, handlers can be used to execute security processing actions such as digital signing of the SOAP messages, executing the access rights control for a service request, or creating an audit event for the Java EE .NET interoperability actions. Using a secure object handler can decouple the security process from the business processing logic so that the Java EE .NET interoperability solution can be scalable and more manageable.

Solution

The Secure Object Handler strategy applies to both synchronous, asynchronous and bridge interoperability strategies. In essence, the secure object handler intercepts the service request and adds custom processing logic, such as adding a digital signature, to the incoming business data object. Using the object handler strategy, developers do not need to rewrite the application processing logic because they can modify existing handlers directly or add new handlers, or chained handlers.

With synchronous or asynchronous integration, the Secure Object Handler can take the service requester's message or object, and apply the handler action, such as digital signing, encryption/decryption, or tracking the security actions for security audit or compliance reasons. Using a bridge interoperability strategy via, for example, an Enterprise Service Bus, the Secure Object Handler can act as a "service engine" or transformer process for the inbound or outbound service provider.

Although using a handler is a neat strategy, not all interoperability technologies can support the same implementation approach of creating a Secure Object Handler. The following sections discuss different types of technology options for each interoperability strategy that can implement a Secure Object Handler.

Synchronous Integration

Synchronous integration enables a Java client to interoperate with a .NET application in a synchronous mode, and vice versa for a .NET client with a Java application. In the synchronous communication between the service requester (client) and the service provider (application), the client waits in a "blocked state," in which no processing or communication with other processes are made until the service provider completes the service request.

.NET Remoting and RPC-style Web services are examples of synchronous integration technologies. .NET implemented in C#, for example, implements the notion of a handler programmatically at the application code level. The client needs to invoke the handler explicitly. If a developer needs to change the handler or update the processing logic in the handler, he or she needs to modify the application codes, recompile, test, and deploy them again.

Listing 13-11 shows a sample secure object handler code that processes a group of service requests (in string array). If the incoming service request contains the string password, then the client invokes the handler Encrypting to encrypt the service request. If the incoming service request contains the string creditCard or cashPayment, then the client invokes the handler DigitalSigning to perform digital signature. If the service request contains the string news, the client invokes the handler SecureLogging to log the service request for audit control.

Listing 13-11. Sample Secure Object Handler in .NET Using Synchronous Integration

using System; /// <summary> /// Abstract class definition for handler /// </summary> abstract class Handler { protected Handler succeedBy; /// <param name="succeedBy" type="Handler"> ///set next successor to the current method</param> public void SetSuccessor(Handler succeedBy) { this.succeedBy = succeedBy; } /// <param name="serviceRequest" type="string"> ///invoking secure object handler</param> abstract public void SecureObjectHandler(string serviceRequest); } /// <summary> /// Encrypting handler will encrypt the data object or message /// using XML-Encryption and WS-Security /// </summary> class Encrypting: Handler { /// <param name="serviceRequest" type="string"> ///invoking secure object handler for Encrypting</param> override public void SecureObjectHandler(string serviceRequest) { if (serviceRequest == "password") // // add your encryption processing logic Console.WriteLine("'{0}' secure object handler processed for '{1}'", this, serviceRequest); else if (succeedBy != null) succeedBy.SecureObjectHandler(serviceRequest); } } /// <summary> /// Digital Signing handler will digitally sign the data /// object or message using /// XML-Signature and WS-Security /// </summary> class DigitalSigning : Handler { /// <param name="serviceRequest" type="string"> ///invoking secure object handler DigitalSigning</param> override public void SecureObjectHandler(string serviceRequest) { if ((serviceRequest == "cashPayment") || (serviceRequest == "creditCard")) // // add your digital signing processing logic Console.WriteLine("'{0}' secure object handler processed for '{1}'", this, serviceRequest); else if (succeedBy != null) succeedBy.SecureObjectHandler(serviceRequest); } } /// <summary> /// SecureLogging handler will log the user info and business /// transaction reference /// for audit trail and/or compliance /// </summary> class SecureLogging : Handler { /// <param name="serviceRequest" type="string"> ///invoking secure object handler SecureLogging</param> override public void SecureObjectHandler(string serviceRequest) { if (serviceRequest == "news") // // add your secure logging processing logic Console.WriteLine("'{0}' secure object handler processed for '{1}'", this, serviceRequest); else if (succeedBy != null ) succeedBy.SecureObjectHandler(serviceRequest); } } /// <summary> /// Client class to invoke a business transaction or service /// request. /// The secure object handler will be invoked. /// </summary> public class Client { /// <summary> /// Main method for Client class /// </summary> public static void Main(string[] args) { // Setup Chain of Responsibility Handler encrypting = new Encrypting(); Handler digitalSigning = new DigitalSigning(); Handler secureLogging = new SecureLogging(); encrypting.SetSuccessor(digitalSigning); digitalSigning.SetSuccessor(secureLogging); // Generate and process serviceRequest string[] serviceRequests = {"password", "creditCard", "cashPayment", "news", "others"}; Console.WriteLine("Secure Object Handler for Synchronous Integration - Example"); Console.WriteLine(); Console.WriteLine(); foreach (string serviceRequest in serviceRequests) encrypting.SecureObjectHandler(serviceRequest); Console.Read(); } }

RPC-style synchronous Web services usually have support of handlers at the container level. For example, Sun Java Web Services Developer Pack (JWSDP) version 1.6 and Apache Axis version 1.2 allow developers to add handlers without modifying the application codes. In JWSDP, developers can specify a configuration file for their server security environment configuration, such as the certificate alias of the digital signature and the name of the handler. Refer to Listing 13-12 for the sample configuration file. The sample handler SecurityEnvironmentHandler.java is an implementation of a CallbackHandler that provides digital signature and encryption functionality. The application codes do not need to embed any of the security processing logic.

Listing 13-12. Sample Security Environment Configuration File wsse.xml in JWSDP

<xwss:JAXRPCSecurity xmlns:xwss="http://java.sun.com/xml/ns/xwss/config"> <xwss:Service> <xwss:SecurityConfiguration dumpMessages="true"> <xwss:Sign> <xwss:X509Token certificateAlias="s1as"/> </xwss:Sign> <xwss:Encrypt> <xwss:X509Token certificateAlias="wse2client"/> </xwss:Encrypt> </xwss:SecurityConfiguration> </xwss:Service> <xwss:SecurityEnvironmentHandler> com.sun.xml.wss.sample.SecurityEnvironmentHandler </xwss:SecurityEnvironmentHandler> </xwss:JAXRPCSecurity>

When building secure object handlers for synchronous integration, developers need to ensure the client is properly authenticated with the server and authorized for the business services prior to invoking the services. This is to ensure that no unauthorized user can invoke the business service. Having these security measures in place addresses the risks of confidentiality, principal spoofing, repudiation, broken authentication, and broken access control.

Asynchronous Integration

Asynchronous integration is loosely coupled interaction between the service requester (client) and the service provider (server). Unlike synchronous integration, asynchronous integration does not require that the client go into a blocked state until the processing of the service request is complete.

Document-style Web service is a common example of asynchronous integration using Web services. It encapsulates the service request or the reply in the form of a message, which can be encrypted or decrypted for confidentiality and digitally signed for non-repudiation. Synchronous integration also uses the same handler mechanism in the Web services container, such as JWSDP or Axis, as discussed earlier, to encapsulate the security processing logic.

When building secure object handlers, asynchronous integration requires similar security requirements, such as authenticating the service requester with the server, as in synchronous integration. The emphasis is on securing the message instead of securing the service requester or the service provider. The sender of the message can be authenticated prior to sending the message. Alternatively the message can be authenticated, digitally signed with a valid certificate for example, and verified intact or not being modified upon receipt to ensure that it is a valid message. Having these security measures in place would address the risks of message alteration, message replay, and repudiation.

Integration Using Enterprise Service Bus

Java EE .NET interoperability using a bridge or an Enterprise Service Bus (ESB) supports both synchronous and asynchronous integration strategies. The bridge or ESB acts as an intermediary between the Java and .NET platform. The security requirements of both synchronous and asynchronous integration strategies discussed earlier also apply to the ESB integration strategy.

ESB has recently become a common example of interoperability in a Service Oriented Architecture (SOA) environment probably because of the multi-messaging protocol and agility in integrating heterogeneous platforms. Not all ESB products support the implementation of a handler. In the example of Mule ESB (http://mule.codehaus.org), Mule allows handlers to be added to an inbound or outbound process. Listing 13-13 shows an example of a Mule ESB configuration where the tag inboundTransformer can specify a secure object handler. The object SecureObjectHandler is a Java class in the current class path that can be programmed to perform security processing such as digital signature for the incoming messages or service requests. Similarly, a secure object handler can be added under the tag outboundTransformer to embed any security processing for outbound messages or reply. For example, all replies to the service requests need to be encrypted and digitally signed using a Secure Object Handler.

Listing 13-13. Sample Mule ESB Configuration to Specify a Secure Object Handler

<?xml version="1.0" encoding="UTF-8"?> ... <mule-configuration version="1.0"> <connector name="SystemStreamConnector" className="org.mule.providers.stream.SystemStreamConnector"> <properties> ... </properties> </connector> <model name="MuleClient"> <mule-descriptor name="ESBClient" inboundEndpoint="stream://System.in" inboundTransformer="SecureObjectHandler" outboundEndpoint="vm://mule/receive" implementation="com.sun.esb.samples.MuleClient"> </mule-descriptor> </model> </mule-configuration>

The technology details for creating a handler vary depending on the ESB product used. It is important to ensure that the client using the ESB is properly authenticated. Moreover, the ESB product adopted should allow adding or modifying Secure Object Handlers without changing the application processing logic.

Creating Handlers

There is no common or standard way to implement handlers. For example, developers can use a callback handler design approach to include the security processing logic. For instance, JWSDP has a sample handler SecurityEnvironmentHandler.java in the samples directory. Each platform or product may have different mechanisms to implement and customize Secure Object Handlers. The following design considerations can apply regardless of the platform chosen:

  • Decouple the security processing logic from the business processing logic. Factor the common security processing logic, such as digital signing, into a Secure Object Handler.

  • Use the application server infrastructure, such as JWSDP with Sun Java System Application Server, to support chained handlers if possible. Refer to earlier sample configuration files.

  • Use a policy framework to implement handlers because policy is declarative and is easier to make changes to when compared to implementing handlers programmatically. Listing 13-14 shows an example of specifying the handler in the application configuration file policyCache.config, which can be generated by using the built-in WSE policy editor.

Listing 13-14. Sample policyCache.config File

[View full width]

<?xml version="1.0" encoding="utf-8"?> <policyDocument xmlns="http://schemas.microsoft.com/wse/2003/06/Policy"> <mappings xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy"> <!--The following policy describes the policy requirements for the service: http://localhost:8080/OrderService/OrderService .--> <endpoint uri="http://localhost:8080/OrderService/OrderService"> <defaultOperation> <request policy="#Sign-X.509" /> <response policy="" /> <fault policy="" /> </defaultOperation> </endpoint> </mappings> <policies xmlns:wsu="http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-wssecurity-utility-1.0.xsd" xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy" xmlns:wssp="http://schemas.xmlsoap.org/ws/2002/12/secext" xmlns:wse="http://schemas.microsoft.com/wse/2003/06/Policy" xmlns:wsse="http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"> <wsp:Policy wsu:> <!--MessagePredicate is used to require headers. This assertion should be used along with the Integrity assertion when the presence of the signed element is required. NOTE: this assertion does not do anything for enforcement (send-side) policy.--> <wsp:MessagePredicate wsp:Usage="wsp:Required" Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part"> wsp:Body() wsp:Header(wsa:To) wsp:Header(wsa:Action) wsp:Header(wsa:MessageID) wse:Timestamp() </wsp:MessagePredicate> <!--The Integrity assertion is used to ensure that the message is signed with X.509. Many Web services will also use the token for authorization, such as by using the <wse:Role> claim or specific X.509 claims.--> <wssp:Integrity wsp:Usage="wsp:Required"> <wssp:TokenInfo> <!--The SecurityToken element within the TokenInfo element describes which token type must be used for Signing.--> <wssp:SecurityToken> <wssp:TokenType> http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1 .0#X509v3 </wssp:TokenType> <wssp:TokenIssuer> CN=Root Agency </wssp:TokenIssuer> <wssp:Claims> <!--By specifying the SubjectName claim, the policy system can look for a certificate with this subject name in the certificate store indicated in the application's configuration, such as LocalMachine or CurrentUser. The WSE X.509 Certificate Tool is useful for finding the correct values for this field.--> <wssp:SubjectName MatchType="wssp:Exact"> CN=WSE2QuickStartClient </wssp:SubjectName> <wssp:X509Extension O MatchType="wssp:Exact">gBfo0147lM6cKnTbbMSuMVvmFY4= </wssp:X509Extension> </wssp:Claims> </wssp:SecurityToken> </wssp:TokenInfo> <wssp:MessageParts Dialect= "http://schemas.xmlsoap.org/2002/12/wsse#part"> wsp:Body() wsp:Header(wsa:Action) wsp:Header(wsa:FaultTo) wsp:Header(wsa:From) wsp:Header(wsa:MessageID) wsp:Header(wsa:RelatesTo) wsp:Header(wsa:ReplyTo) wsp:Header(wsa:To) wse:Timestamp() </wssp:MessageParts> </wssp:Integrity> </wsp:Policy> </policies> </policyDocument>

WSE 2.0 provides a configuration editor that reads the input from the app.config or Web.config file and generates the policy cache file in Listing 13-14. (Refer to the "Example" section later in the chapter for more details.) The policy Sign-X.509 and the handler details are referenced in the app.config or Web.config file. If the incoming SOAP request with the element <wsse:BinarySecurityToken> does not contain the appropriate binary security token that meets the policy defined here, an exception is thrown.

If a developer wants to a add new handler, he can write a custom policy assertion handler that is derived from the Microsoft.Web.Services.Policy.PolicyAssertion class and register it in the app.config or Web.config file. Refer to Listing 13-15 for an example.

Listing 13-15. Adding a Custom Handler in the app.config or Web.config Configuration Files

using Microsoft.Web.Services.Policy; public class MySecureObjectHandler : PolicyAssertion { // add your customized security processing logic here // to override the member functions } In the app.config or Web.config configuration file, you need to add an assertion element to the policy section. This assertion element maps a policy assertion element name (such as wsp:MessagePredicate) and registers it in the configuration file. <?xml version="1.0" encoding="utf-8"?> <configuration> <configSections> … </configSections> <microsoft.web.services> <policy> <receive> <cache name="policyCache.xml"/> </receive> <assertion name="wsp:MessagePredicate" type="SecureObjectHandler" xmlns:wsp="…" /> </policy> </microsoft.web.services> … </configuration>

In JWSDP, a handler can be customized to extend a callback handler. Listing 13-16 shows a sample template where you can customize your handlers under the public method "handle." For details, please refer to the JWSDP API documentation to implement a callback handler.

Listing 13-16. Sample SecurityEnvironmentHandler Callback Handler Template in JWSDP

import javax.security.auth.callback.Callback; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.UnsupportedCallbackException; import com.sun.xml.wss.impl.callback.CertificateValidationCallback; import com.sun.xml.wss.impl.callback.DecryptionKeyCallback; import com.sun.xml.wss.impl.callback.EncryptionKeyCallback; import com.sun.xml.wss.impl.callback.PasswordCallback; import com.sun.xml.wss.impl.callback.PasswordValidationCallback; import com.sun.xml.wss.impl.callback.SignatureKeyCallback; import com.sun.xml.wss.impl.callback.SignatureVerificationKeyCallback; import com.sun.xml.wss.impl.callback.UsernameCallback; import com.sun.org.apache.xml.security.utils.RFC2253Parser; // insert your additional Java class libraries... … public class SecureObjectHandler implements CallbackHandler { // ... public SecureObjectHandler() throws Exception { // define your constructor details } public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { for (int i=0; i < callbacks.length; i++) { if (callbacks[i] instanceof PasswordValidationCallback) { // implement your own password validation processing // logic } else if (callbacks[i] instanceof SignatureVerificationKeyCallback) { // implement your own digital signature verification // processing logic } else if (callbacks[i] instanceof SignatureKeyCallback) { // implement your own signature key processing logic } else if (callbacks[i] instanceof DecryptionKeyCallback) { // implement your own decryption key processing logic } else if (callbacks[i] instanceof EncryptionKeyCallback) { // implement your own encryption key processing logic } else if (callbacks[i] instanceof CertificateValidationCallback) { // implement your own digital certificate validation // processing logic } else { throw unsupported; } } } // ... }

It's best to use known interoperable encryption key or session algorithms. For example, RSA Optimal Asymmetric Encryption Padding (RSAOREA) and Triple DES are interoperable between .NET and JWSDP.

Example

This example illustrates a .NET client (Retailer) placing a purchase order with the service provider (Manufacturer). The .NET client invokes a purchase order Web service from a Java application service with the details of the account number, SKU number, supplier item number, and quantity. Upon completion of the purchase order submission, the service provider returns a receipt number.

The .NET client uses the installed X.509 certificate to sign the service request and encrypt the business data. The JWSDP server validates the message digest and decrypts the business data. This example demonstrates the interoperability of the digital signature and the encryption/decryption between the .NET client and the JWSDP server using Web services security.

Gates provides a comprehensive example for Java EE .NET interoperability. See [SGuest] for more details.

Assumptions

The following software components need to be installed and configured on the same machine:

  • Java Web Services Developer Pack (JWSDP) version 1.5 (http://java.sun.com/webservices/downloads/webservicespack.html) A Tomcat container customized for JWSDP (http://java.sun.com/webservices/containers/tomcat_for_JWSDP_1_5.html) also must be installed. Please note that the standard Apache Tomcat server is not compatible here. In this example, the product is installed under C:\Tools\Tomcat. Please refer to the product installation documentation for details.

  • Web Services Enhancement 2.0 SP1 (http://msdn.microsoft.com/webservices/) In this example, the product is installed under the default directory C:\Program Files\Microsoft WSE\v2.0. Please refer to the product installation documentation for details.

  • .NET Framework SDK version 1.1 (http://msdn.microsoft.com/netframework/downloads/framework1_1) In this example, the product is installed under the default directory C:\Program Files\Microsoft.NET\SDK\v1.1. Please refer to the product installation documentation for details.

  • Java 2 Standard Edition SDK version 1.5.0_03 http://java.sun.com/j2se/1.5.0/download.jsp)

Prerequisites

To illustrate security interoperability using Web services security, this example requires the following:

  • .NET client installs a sample X.509 certificate entitled WSE2QuickStartClient ("Client Private.pfx") from the WSE 2.0 (under C:\Program Files\Microsoft WSE\v2.0\Samples\Sample Test Certificates). The public key of the client certificate also must be imported into the Java Keystore via Microsoft Management Console (mmc.exe) as the name "wse2client.cer" under C:\Tools\JWSDP\xws-security\etc.

  • Using the WSE2QuickStartClient certificate, the root agency must be exported to a file wse2ca.cer under C:\Tools\JWSDP\xws-security\etc.

  • JWSDP server uses the sample X.509 certificates from the JWSDP distribution. Export the JWSDP server (server.cer) and root agency (ca.cer) certificates from the keystores server-keystore.jks and server-truststore.jks under the same directory C:\Tools\JWSDP\xws-security\etc).

  • Install a JCE RSA provider. In this example, the latest Bouncy Castle JCE provider (BCP) for Java 2 SE SDK (aka JDK) version 1.5 (www.bouncycastle.org/latest_releases.html) is used. Ensure that the BCP version (such as BCP for JDK 1.5) matches the same JDK version number (such as JDK 1.5) for compatibility.

  • The .NET client is configured with a WS-Security setting of XML signature and encryption using the built-in WSE Configuration Editor.

  • The JWSDP server is configured with the default SecurityEnvironmentHandler to provide XML signature and decryption/encryption.

Procedures

  1. Install .NET Client Certificate.

    Go to C:\Program Files\Microsoft WSE\v2.0\Samples\Sample Test Certificates and double-click the file Client Private.pfx. This should start the Certificate Import Wizard to install the certificate and private key. The Certificate Import Wizard prompts you for the password (which is wse2qs). Select the target folder location as "Personal."

    To verify the import operation, you can open Microsoft Management Console (mmc.exe) to browse the entry WSE2QuickStartClient from the Personal folder. This can be done by running the command mmc.exe from the Start/Run of the Windows environment. Then select File/Add/Remove Snap-in…/Add/Certificates/My User Account. Microsoft Management Console (MMC) should then show a hierarchy of certificates folders under "Console Root"/"Certificates Current User" (refer to Figure 13-6).

    Figure 13-6. Verifying client certificate that is imported

    Now you can export the public part of the WSE2QuickStartClient certificate to the Java keystore under C:\Tools\Tomcat\xws-security\etc. Open the Microsoft Management Console (as depicted earlier in Figure 13-6). From the MMC, right-click the WSE2QuickStartClient entry and select "All Tasks | Export" to export the private key in "Base 64 CER" export type under the file name C:\Tools\Tomcat\xws-security\etc\wse2client.cer.

    After that, double-click the WSE2QuickStartClient certificate again, select the Certification Path tab and double-click the Root Agency certificate. Then click the Details tab and select the Copy to File button to save the root agency certificate as C:\Tools\Tomcat\xws-security\etc\wse2ca.cer.

    To import these client certificates into Java keystore server-truststore.jks so that the JWSDP server application can process the XML signature and decryption using the public key, invoke the following commands:

    keytool import file wse2client.cer alias wse2client keystore server-truststore.jks keytool -import -file wse2ca.cer -alias wse2ca -keystore server-truststore.jks

    You can verify the import operation by the following commands (refer to Listing 13-17):

    Listing 13-17. Verifying Import of .NET Client Certificate

    C:\Tools\Tomcat\xws-security\etc>keytool -printcert -file wse2client.cer Owner: CN=WSE2QuickStartClient Issuer: CN=Root Agency Serial number: -3abb68e8ca769e74b1998659471cf56e Valid from: Tue Jul 08 11:47:59 PDT 2003 until: Sat Dec 31 15:59:59 PST 2039 Certificate fingerprints: MD5: 72:52:48:7C:00:45:53:94:38:BE:47:5B:15:00:80:37 SHA1: CA:76:01:38:1B:45:78:50:2B:62:B8:80:98:25:66:4F:1E:78:DF:A2 C:\Tools\Tomcat\xws-security\etc>keytool -printcert -file wse2ca.cer Owner: CN=Root Agency Issuer: CN=Root Agency Serial number: 6376c00aa00648a11cfb8d4aa5c35f4 Valid from: Tue May 28 15:02:59 PDT 1996 until: Sat Dec 31 15:59:59 PST 2039 Certificate fingerprints: MD5: C0:A7:23:F0:DA:35:02:6B:21:ED:B1:75:97:F1:D4:70 SHA1: FE:E4:49:EE:0E:39:65:A5:24:6F:00:0E:87:FD:E2:A0:65:FD:89:D4

  2. Install JWSDP Server Certificate.

    Go to C:\Tools\Tomcat\xws-security\etc and run the following commands to export the sample JWSDP server certificates:

    keytool export file server.cer alias s1as keystore server-keystore.jks keytool -export -file ca.cer -alias certificate-authority -keystore server-truststore.jks

    To verify the export operation, you can use the following commands (refer to Listing 13-18):

    Listing 13-18. Verifying Export of JWSDP Server Certificate

    C:\Tools\Tomcat\xws-security\etc>keytool -printcert -file server.cer Owner: CN=Server, OU=JWS, O=SUN, ST=Some-State, C=AU Issuer: CN=RootCA 2005, OU=JWS, O=SUN, ST=Some-State, C=IN Serial number: 2 Valid from: Mon Apr 11 22:37:29 PDT 2005 until: Tue Apr 11 22:37:29 PDT 2006 Certificate fingerprints: MD5: 5E:F1:DB:6F:66:22:C6:AC:E8:C3:D9:73:35:C7:2C:AC SHA1: F0:67:9A:4E:1C:FD:F5:F0:C7:39:F7:94:08:3A:EF:54:B3:14:71:12 C:\Tools\Tomcat\xws-security\etc>keytool -printcert -file ca.cer Owner: CN=RootCA 2005, OU=JWS, O=SUN, ST=Some-State, C=IN Issuer: CN=RootCA 2005, OU=JWS, O=SUN, ST=Some-State, C=IN Serial number: 0 Valid from: Mon Apr 11 22:28:27 PDT 2005 until: Thu Apr 09 22:28:27 PDT 2015 Certificate fingerprints: MD5: 3D:B5:3C:93:F5:65:D5:3D:B5:C5:2E:23:F5:2E:3A:E9 SHA1: 98:5F:43:96:C0:ED:A5:88:19:DC:D2:1A:2F:8A:5E:0E:44:42:D7:A1

  3. Install JCE RSA Provider.

    Install the Bouncy Castle JCE provider under the Java 2 SE SDK (JDK) directory. In this example, install under C:\Tools\JDK15\jre\lib\ext. Edit your java.security policy file under the JDK installation to add the new JCE provider. Please note that the order of the JCE provider may cause compatibility issues. From experience, add the Bouncy Castle JCE provide after the Sun RSA provider (refer to Listing 13-19).

    Listing 13-19. Adding Bouncy Castle JCE Provider in java.security

    # # List of providers and their preference orders (see above): # security.provider.1=sun.security.provider.Sun security.provider.2=sun.security.rsa.SunRsaSign security.provider.3=com.sun.net.ssl.internal.ssl.Provider security.provider.4=com.sun.crypto.provider.SunJCE security.provider.5=org.bouncycastle.jce.provider.BouncyCastleProvider security.provider.6=sun.security.jgss.SunProvider security.provider.7=com.sun.security.sasl.Provider

  4. Configure .NET Client Policy.

    Open the .NET WSE configuration file app.config or Web.config using the WSE Configuration Editor (refer to Figure 13-7). This should enable the .NET client side to support XML signature and XML encryption for Web services security.

    Figure 13-7. Using WSE Configuration Editor to define XML signature and XML encryption

  5. Configure JWSDP Security Handler.

    On the JWSDP server side, edit the wsse.xml configuration file that JWSDP uses to configure Web services security. The previous shows an example of the configuration file content with both XML signature and XML encryption turned on.

  6. Compile and Deploy JWSDP Application.

    After the Web services security features are turned on in the JWSDP server application, you can compile and deploy your server application. This example uses an ant script to compile and deploy to JWSDP. For example

    C:\Dev\Lab\wsi-wse\wsdp\service>ant build-all Buildfile: build.xml … build-all: BUILD SUCCESSFUL Total time: 19 seconds

  7. Compile and Invoke .NET Client.

    Once the Web services security features are turned on in the .NET client, you can compile your client application, for example:

    C:\Dev\Lab\wsi-wse\dotnet\Client>csc /out:Client.exe *.cs proxy\OrderProxy.cs /r:"c:\program files\microsoft wse\v2.0\Microsoft.Web.Services2.dll" Microsoft (R) Visual C# .NET Compiler version 7.10.6310.4 for Microsoft (R) .NET Framework version 1.1.4322 Copyright (C) Microsoft Corporation 2001-2002. All rights reserved.

    In this example, the .NET client application is called Client.exe, which is compiled from the existing C# programs in the directory C:\Dev\Lab\wsi-wse\dotnet\Client.

Result

The .NET client generates a service request to create a purchase order and renders the following XML message (refer to Listing 13-20). The header contains the key Web Services Security information <wsse:Security>, which includes the elements <wsse:BinarySecurityToken /> and <ds:Signature />. The body contains the core business data <submitOrderResponse />.

Listing 13-20. Service Request to Create a Purchase Order from a .NET Client

[View full width]

<?xml version="1.0" encoding="utf-8"?> <log> <env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:ns0="http://wss.samples.microsoft.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <env:Header> <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-wssecurity-secext-1.0.xsd" env:mustUnderstand="1"> <wsse:BinarySecurityToken xmlns:wsu="http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-wssecurity-utility-1.0.xsd" EncodingType="http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:> MIIC8zCCAlygAwIBAgIBAjAN … Q3u1+58HZRLS97o+vmKy84OE </wsse:BinarySecurityToken> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <ds:Reference URI="#Id-1069588494982330250"> <ds:Transforms> <ds:Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue> FD+aZWI8zxgIuqsE9/LbHeGkiuI= </ds:DigestValue> </ds:Reference> <ds:Reference URI="#Id1298574802901223328"> <ds:Transforms> <ds:Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#sha1" /> <ds:DigestValue> 0joA2wLLMj9ZzPMRPEufAv14keI= </ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue> qeYG9xwdSxIMYXi7c4wby5bQkPsqVdOIgi0RbQHW237 … </ds:SignatureValue> <ds:KeyInfo> <wsse:SecurityTokenReference> <wsse:Reference URI="#Id-4853980734745059755" ValueType= "http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-x509-token-profile-1.0#X509v3" /> </wsse:SecurityTokenReference> </ds:KeyInfo> </ds:Signature> <wsu:Timestamp xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1 .0.xsd" wsu:> <wsu:Created> 2005-06-28T14:46:42Z </wsu:Created> <wsu:Expires> 2005-06-28T14:51:42Z </wsu:Expires> </wsu:Timestamp> </wsse:Security> </env:Header> <env:Body xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:> <ns0:submitOrderResponse> <result>2233444</result> </ns0:submitOrderResponse> </env:Body> </env:Envelope> </log>

The JWSDP server application receives the service request and returns a receipt number in XML (refer to Listing 13-21):

Listing 13-21. Response to the Purchase Order Request by JWSDP Server Application

[View full width]

<?xml version="1.0" encoding="utf-8"?> <log> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing" xmlns:wsse= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"> <soap:Header> <wsa:Action wsu:> </wsa:Action> <wsa:MessageID wsu:> uuid:119831ce-58be-4cd1-b70f-77e7ad96552f </wsa:MessageID> <wsa:ReplyTo wsu:> <wsa:Address> http://schemas.xmlsoap.org/ws/2004/03/addressing/role/anonymous </wsa:Address> </wsa:ReplyTo> <wsa:To wsu:Id= "Id-1f1db802-65c0-43d3-9af1-167208ce98e4"> http://localhost:8080/OrderService/OrderService </wsa:To> <wsse:Security soap:mustUnderstand="1"> <wsu:Timestamp wsu:Id= "Timestamp-d65bb998-7c43-4efc-808c-2304d8a13d79"> <wsu:Created>2005-06-28T14:45:59Z</wsu:Created> <wsu:Expires>2005-06-28T14:50:59Z</wsu:Expires> </wsu:Timestamp> <wsse:BinarySecurityToken ValueType= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1 .0#X509v3" EncodingType= "http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-soap-message-security-1.0#Base64Binary" xmlns:wsu= "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1 .0.xsd" wsu:Id= "SecurityToken-1ecd5e58-9ba6-4239-a9fb-250e15dc3769">MIIBxDCCAW6gAwIBAgIQx USXFzWJYYtOZnmmuOMKkjANBgkqhkiG9w0BA Q...F5qkh6sSdWVBY5sT/txBnVJGziyO8DPYdu2fPMER8ajJfl </wsse:BinarySecurityToken> <Signature xmlns="http://www.w3.org/2000/09/xmldsig#"> <SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" /> <SignatureMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#rsa-sha1" /> <Reference URI="#Id-8f3d108c-3186-4eac-bd30-8584e82fa38d"> <Transforms> <Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue> yHqfuGhCwnU/guHlvPy5j8vZDC0= </DigestValue> </Reference> <Reference URI="#Id-c00ca163-3d7b-4cec-8e7a-791546d41e15"> <Transforms> <Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue> yM82YC9rZzfb3AWD0iYbNmBT4UM= </DigestValue> </Reference> <Reference URI="#Id-42f224be-c812-473e-b243-eea1f2dd7e66"> <Transforms> <Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue> 5GDwT3MA0YOx4GqugDBtWUyjMnw= </DigestValue> </Reference> <Reference URI="#Id-1f1db802-65c0-43d3-9af1-167208ce98e4"> <Transforms> <Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm= "http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue> nG7Lkpn0W1pMB/BRWiQGltfbyRA= </DigestValue> </Reference> <Reference URI= "#Timestamp-d65bb998-7c43-4efc-808c-2304d8a13d79"> <Transforms> <Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue> 9udH1FbnHV0eq6BQ8wJUof3V+UA= </DigestValue> </Reference> <Reference URI="#Id-42767f08-d88f-4394-a4f3-06bf14b00916"> <Transforms> <Transform Algorithm= "http://www.w3.org/2001/10/xml-exc-c14n#" /> </Transforms> <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" /> <DigestValue> g1QqF2amKSwrGc4EHjgvhpvI4jE= </DigestValue> </Reference> </SignedInfo> <SignatureValue> KlJ1j0…POB6KzPO00= </SignatureValue> <KeyInfo> <wsse:SecurityTokenReference> <wsse:Reference URI= "#SecurityToken-1ecd5e58-9ba6-4239-a9fb-250e15dc3769" ValueType= "http://docs.oasis-open.org/wss/2004/01 /oasis-200401-wss-x509-token-profile-1.0#X509v3" /> </wsse:SecurityTokenReference> </KeyInfo> </Signature> </wsse:Security> </soap:Header> <soap:Body wsu:> <submitOrder xmlns="http://wss.samples.microsoft.com"> <OrderImpl_1 xmlns=""> <accountNumber>LUCKY-200-300-101</creditCardExpM> <quantity>200</quantity> <supplierItemNumber>99882388</supplierItemNumber> <SKU>2233888</SKU> </OrderImpl_1> </submitOrder> </soap:Body> </soap:Envelope> </log>

Benefits and Limitations

Secure Object Handler is a generic implementation approach to abstract common security processing logic and decouple from the application processing logic. It can be used with various Java EE .NET interoperability technologies and has the following benefits:

Maintainability

Common security processing logic can be refactored into Secure Object Handlers to perform pre-processing or post-processing tasks. Developers just need to maintain the handlers centrally instead of modifying massive numbers of applications that have security processing logic embedded.

Scalability

The Java EE .NET interoperability solution can be more manageable if the security processing logic is decoupled from the business processing logic. This allows Java and .NET applications to extend their security processing logic by either extending existing handler functionality or adding a chain of handlers (if the underlying platform or product supports the handlers).

Limitations

There are a few limitations when using handlers. First, there may be existing legacy applications that do not support the use of handlers. For example, .NET applications that do not use WSE do not benefit from the WS-Policy framework. Developers have to modify the applications to add custom handlers, which may cause considerable change on impact and implementation risks.

Second, some integration strategies' implementations can only support one single handler and not multiple handlers. Thus developers need to consolidate all security processing logic into a single handler. This will overload the handler design in one single implementation.

Категории