Web Services Enhancements 1.0 and Java Interoperability, Part 1

 

Simon Guest
Microsoft Corporation

February 2003

Applies to:
   Web Services Enhancements 1.0 for Microsoft&174; .NET
   Microsoft .NET Framework 1.0
   IBM Web Services ToolKit 3.3.2
   SOAP Toolkit 3.0

Summary: Covers interoperability between Web Services Enhancements 1.0 for Microsoft .NET and Java and shows how the WS-Security specification and implementation can be used to securely sign a Web service call from Microsoft .NET to Java and vice versa. The IBM Web Services ToolKit 3.3.2 enables WS-Security functionality for Java. Includes downloadable code samples. (21 printed pages)

Download the WSEWstkInterop.msi code sample.


Contents

Required Software and Skills to Run the Code Samples
Introduction
Installing the Sample Code
Preparing the Environment
Using WS-Security with the IBM WSTK 3.3.2
Using the SOAP Trace Utility to Examine the Results
Conclusion

Required Software and Skills to Run the Code Samples

The following software and skills are required to run the samples in this article.

  • Microsoft. NET Framework 1.0 or higher

    A basic working knowledge of both the .NET Framework and J2SE SDK 1.3 or higher is required. It is assumed that you understand the principles behind writing and compiling an application for both platforms, and that you have a good understanding of the C# and Java language syntax.

  • Web Services Enhancements (WSE) 1.0 for Microsoft .NET

    For the WSE 1.0 sample applications, the following configuration is assumed: Microsoft Windows® XP Professional, Windows 2000 Professional, Windows 2000 Server, Windows 2000 Advanced Server or Windows Server 2003 RC2 installed with v1.0 or higher of the .NET Framework and the Microsoft Web Services Enhancements 1.0 (WSE) download. You should be relatively familiar with the WS-Security samples that are shipped with WSE, as they provide the bases for the samples here.

  • Compliant Java 2 Standard Edition (J2SE) SDK, version 1.3.1 or higher
  • Apache Tomcat 4.0

    For the Java sample applications, a version of the J2SE SDK v1.3 or higher is required. Apache Tomcat v4.0 is required to follow the samples in this article that reference the IBM WSTK 3.3.2.

    For the J2SE SDK, it is assumed that environment variables are correctly set so that the SDK tools can be run from a command line prompt.

  • IBM Web Services ToolKit (WSTK) 3.3.2

    The IBM WSTK 3.3.2 should be installed to the default C:\WSTK-3.3 directory in order for the samples to work.

By default, all of the sample code has been designed to run on a single machine with the following port settings for each sample.

  • Microsoft IIS / Microsoft ASP.NET – localhost:80
  • Apache Tomcat 4.0 / IBM WSTK 3.3.2 – localhost:8080

This article demonstrates how the code itself runs without having two or more tiers set up for installation. Taking the sample code and running across multiple machines requires replacing the references to 'localhost' within the configuration and sample code. Many of these can be found in the final section of this article, where we use the SOAP Trace Utility to monitor the calls between the two.

Introduction

This article shows a working example of using the WS-Security specification and implementation to sign a Web service request with X.509 certificates between Microsoft .NET (using WSE) and Java (using the IBM WSTK). This article does not show encryption, which will be featured in a later article.

So, what is the requirement behind using WS-Security for signing Web service requests between .NET and Java? The ability to sign a Web service request guarantees that the message contents have not been altered during transit. Using a digital certificate, it is possible to sign a Web service request with a private key, so that it can only be validated with the corresponding public key.

Until now, there have been two options for securing Web services: one at the transport level (using SSL), and another at the application level, using a custom security mechanism. Both of these options, while technically effective, have some limitations or drawbacks for adoption.

Security at the transport level using SSL can be used to guarantee the integrity of a Web service request by securing the underlying transport layer (HTTP). SSL can be used both to encrypt the link and to validate the client and server using certificates.

One of the main problems in using SSL to secure Web services is that the security is only effective from a single point to another. As the SSL communication is based on the transport, once the end point has been reached, this method of securing the message is no longer applicable. For example, if I send a message from Client A to Server B, I can use SSL to secure the link. If, however I send a message from Client A to Server C—and it has to go via Server B—there is no easy way to ensure the security of the message using SSL through this intermediary.

It is also possible to develop a custom security mechanism where the contents of the message and headers were signed at the client and checked at the server. This would overcome the transport security issue, but in the end this would be a custom solution. Organizations that wish to secure Web services that are made public to other organizations would have to ensure that the same technology is used at each of the end points.

WS-Security solves both of these problems by providing an application-based way of signing the Web service (to avoid issues seen with securing at the transport layer) using an openly published standard that can be referenced and adopted by customers, system integrators, and vendors.

To help promote this standard, this article will show a series of Web signing samples between two implementations of WS-Security: one for Microsoft .NET, based on Microsoft Web Services Enhancements (WSE) 1.0, and the other based on the IBM Web Services ToolKit (WSTK).

The setup that we will be showing is similar to the following:

Figure 1. Microsoft .NET client using WSE 1.0 to call .NET-based and Java Web services

As in Figure 1, with each of the toolkits, we will show two sets of examples: first, a .NET client calling the WSE Web service and the IBM WSTK, and second, a Java client calling the WSE Web service and the IBM WSTK Web service, as shown in Figure 2.

Figure 2. Java client using IBM WSTK to call .NET-connected and Java Web Services

This article is not intended to be a comparison of any of the toolkits (given the early stages of the specifications, this would not be fair), and is instead intended to show interoperability with Web services between Microsoft .NET and Java.

The samples shown here are designed to replicate the 'Add Integer' sample that ships with the WSE 1.0 release. You may wish to go through that sample code before trying out any of the code samples used here .

Installing the Sample Code

All of the samples are contained in a downloadable .msi file. By default, the samples install to a C:\wse-interop directory. For the purposes of running the sample code and following this article, I recommend that you do not change the directory name.

After you have installed the sample code, the \wse-interop sample directory contains a number of subdirectories:

  • dotNETWebService: This contains the .NET-connected Web service that will be called by the WSE and IBM WSTK clients.
  • JKS: This directory contains the Java Key Store that will be used for signing the Web service requests.
  • WSTK: This directory contains the sample code for the IBM WSTK.

Preparing the Environment

Before we can run the sample code, we need to set up the environment on which the Web services are going to run. This includes creating the .NET-connected Web service, configuring the IBM WSTK, and setting up certificates that are going to be used for the samples.

Setting Up the .NET-Connected Web Service

Following installation, the .NET-connected Web service can be found in the C:\wse-interop\dotNETWebService directory. In order for the Web service to be able to process requests, we must first build the solution and create a virtual directory within Microsoft Internet Information Services (IIS).

In order to build the solution, run the Build.bat script from the C:\wse-interop\dotNETWebService directory. This build script compiles the Web service. The Build.bat script does use the command line C# compiler (Csc.exe). You may want to ensure that this file is in your path. For version 1.0 of the .NET Framework, Csc.exe can be found in the C:\Windows\Microsoft.NET\Framework\v1.0.3705 directory.

Alternatively, you may also take the entire contents of this directory into Microsoft® Visual Studio® .NET and compile from there.

To create the IIS virtual directory

  1. To run the Internet Information Services administrative tool, on the Administrative Tools menu, click Internet Information Services (or click Start, click Run, and then type Inetmgr.exe). The Internet Information Services Manager dialog box opens, as shown in Figure 3.

    Figure 3. Internet Information Services console

  2. In the left pane of the Internet Information Services Manager dialog box, right-click Default Web Site. On the shortcut menu, click New..., and then click Virtual Directory. The Virtual Directory Creation Wizard opens. In the wizard, click Next.
  3. Under Alias:, type WSEX509Interop as shown in Figure 4. The exact name and case for this alias is important, as it is referenced in the sample code. Although you can change it later, it is recommended that you use this name in order to get the samples working.

    Figure 4. Entering the alias for the virtual directory

  4. Click Next to display the directory location, and type C:\wse-interop\dotNETWebService as shown in Figure 5. This is the location of the sample files.

    Figure 5. Setting the location for the .NET-connected Web service

  5. Click Next and accept of the other defaults until the wizard is completed.

The .NET-connected Web service is now configured. Use Microsoft Internet Explorer to browse to http://localhost/WSEX509Interop/Service1.asmx and test the publication. The Web service publishes an AddInt WebMethod. This WebMethod will not work from Internet Explorer, however, as it requires to be called via a SOAP request.

Building the Sample Code for the IBM WSTK 3.3.2

The C:\wse-interop\WSTK\X509Signing directory contains the sample code for the IBM WSTK. Within this directory are two subdirectories: Services and dotNETClient.

The Services directory contains the sample code for the WSTK service and WSTK client, which will be deployed to Apache Tomcat. The dotNETClient directory contains the sample code for the .NET client.

In order to install the sample code for the IBM WSTK, perform the following:

  1. Within the Services directory are two further subdirectories: addint and dsigdotnet. Copy these two subdirectories to the default WSTK services directory (if the defaults have been accepted during the IBM WSTK installation, this is C:\WSTK3-3\services\demos).
  2. After these directories have been copied, ensure that the Apache Tomcat service is stopped, navigate to the C:\WSTK-3.3\bin directory, and run Wstkconfig.bat in order to configure these demo services.

    In the Web Services ToolKit Configuration Tool, click the ConfigureServices tab. This tab lists the demo services that are going to be installed as part of the Wstk.war file created for the Tomcat Server.

    Figure 6. Configuring the services in IBM WSTK 3.3.2

    Within this tab, ensure that the demos\addint and demos\dsigdotnet services are selected.

  3. Accept the rest of the defaults for the WSTK Configuration Tool. When you finished using the tool, the Wstk.war file is created and deployed to the Tomcat directory.

    The configuration for the IBM WSTK 3.3.2 is now complete.

Configuring the Certificate Stores

In order to sign SOAP messages being sent to or received from a Web service hosted on either .NET or through the IBM WSTK using these samples, we need a process to create X.509 certificates.

We will be dealing with two different certificate infrastructures. The .NET Framework and WSE code uses the built-in Windows certificate infrastructure and the client will access certificates from the current user's certificate store. The Java code uses a Java Key Store to hold certificates and corresponding key information.

Requesting and importing a certificate into Windows

In order to request a certificate for the Windows store, you must have access to a Certificate Authority (CA). This may be a public CA that you have access to, or you can also use Certificate Services that ship with Windows 2000 Server.

For more information about requesting a certificate via Certificate Services, refer to the Microsoft Platform SDK.

To check the presence of a valid certificate

  1. To run the Microsoft Management Console, on the Start menu, click Run, and type Mmc.exe.
  2. On the File menu, click Add/Remove Snap-In, and then click Add.
  3. Select Certificates, click Add, and then select My User Account. Click Close twice to return to the console.
  4. Expand the Certificates / Personal Certificates / Certificates tree. Here you should see a list of certificates specific to the user account of the logged-in user. If you do not see a certificate in this store that can be used for signing, you will need to request one from an available CA.

Creating an entry in the Java Key Store

The WSTK sample code uses a certificate key that is stored in a Java Key Store (JKS). A default JKS, called Keystore.db is installed with the samples, and can be found within the C:\wse-interop\JKS directory.

To administer the JKS, a tool called Keytool.exe (shipped with the J2SE SDK) is used.

To list the contents of the current Keystore.db file, navigate to C:\wse-interop\JKS and run the following command:

keytool –list –keystore keystore.db

The default password for this key store is password (lower case). This command returns the following:

Keystore type: jks
Keystore provider: SUN

Your keystore contains 0 entries:

As shown here, there are no certificates or keys in the Java Key Store. In order to create a key that can be used for signing, use the following command, exactly as shown:

keytool -genkey -keystore keystore.db -alias test –keyalg rsa

Enter the key store password and complete the list of certificate questions presented (Fullname, organization, locality etc.). Although the alias of the key must be called test for the sample code, these other details can be your own and are not specific to the sample code. At the end of the questions, make the password of the test key the same as the keystore password by pressing the Enter key.

Repeat the keytool –list command previously shown. The test key that we have created should now be listed.

test, Sun Jan 12 14:29:46 PST 2003, keyEntry,
Certificate fingerprint (MD5): 91:43:81:C0:C9:22:04:27:22:27:A5:1D:E1:60:E5:8D

The certificate stores are now complete. With these configured and the sample code built, we can now run the samples!

Using WS-Security with the IBM WSTK 3.3.2

In order to show request signing with the IBM WSTK, let's run the sample code to see how it works.

Deploying the WSTK Web Service

The demo code contains two Web services (these were the two directories that were copied and deployed when we set up WSTK earlier).

These two Web services are AddInt and Dsigdotnet. The AddInt Web service is similar to the .NET-connected Web service that we deployed earlier. As with the .NET version, the AddInt Web service accepts two numbers, adds them together and returns the result. The Dsigdotnet Web service is a service that 'fronts' the AddInt Web service, requiring that each incoming Web service request be signed.

With Apache Tomcat running, we need to deploy the AddInt Web service. To do this, navigate to the C:\wstk-3.3\services\demos\addint\deployment directory.

From here run:

deploy.bat deploy.wsdd

This will deploy the AddInt Web service. (The Deploy.bat file is used to deploy WSDD files conveniently and is not a part of the WSTK. You may need to adjust the settings in this file to reflect your own environment.)

To test, you can check out the WSDL for this service by using Internet Explorer to navigate to http://localhost:8080/wstk/addint/services/AddIntService?WSDL.

We also need to follow a similar step in order to deploy the Dsigdotnet Web service. Navigate to the C:\wstk-3.3\services\demos\dsigdotnet\deployment directory and run:

deploy.bat deploy_server.wsdd

This deploys the server-side service for the Dsigdotnet service.

Calling with the .NET Client

The .NET client can be found in the C:\wse-interop\WSTK\X509Signing\dotNETClient directory, calls both the WSE and IBM WSTK Web services, and signs the request.

If you have not done so already, build the client by running Build.bat in this directory and run the Client.exe that is created. As with the sample code supplied with WSE 1.0, you will need to supply the A and B parameters. For example:

CLIENT /a 40 /b 50

The first thing the client does is to request the X.509 certificate with which to sign the request, which then opens the Select Certificate dialog box as shown in Figure 7.

Figure 7. Select Certificate dialog box

Select the certificate that is to be used for signing this request. This should be the same certificate as the one that was imported into the Java Key Store in our previous steps.

If all is successful, the client sample generates the following output:

Key Name                       : C=US, S=WA, L=Redmond, O=Microsoft, OU=.NEAT, C
N=Simon Guest, E=sguest@microsoft.com
Key ID of Certificate selected : 67WE7bDjBnbsb2JUEFvo7qi/iUg=

Calling the WSE 1.0 X509 Service...
90
Calling the IBM WSTK X509 Service...
90

The details of the certificate selected are displayed. Two Web service requests are then made—the first to the WSE Web service, the second to the IBM WSTK Web service. Both these requests are signed with the X.509 certificate that was presented.

Calling with the WSTK Client

As with the other samples applications that ship with v3.3.2 of the IBM WSTK, this client is run from a Java Server Page (JSP) hosted through Apache Tomcat.

If all of the previous configuration steps have been completed, you are able use Internet Explorer to navigate to http://localhost:8080/wstk/dsigdotnet/addint.jsp.

This displays the following:

Please call JSP with HTTP GET parameters a and b. e.g. addint.jsp?a=20&b=30

To supply the A and B integers to add in this sample, append the HTTP GET parameters as shown in the sample. For example, if we wish to use the same values as before with the .NET client, we would call http://localhost:8080/wstk/dsigdotnet/addint.jsp?a=40&b=50.

If all works, the following is displayed in the browser:

Signing and calling the .NET Web Service...
Result is 90 

Signing and calling the IBM WSTK Web Service...
Result is 90

How the WSE 1.0 / IBM WSTK 3.3.2 Sample Works

The key to getting the WSE / WSTK sample to work is in understanding how the WSTK deployment works. Here, we will look at the server and client configuration for the IBM WSTK sample code, and see how that interoperates with WSE.

IBM WSTK sample Web service configuration

Each of the two Web services deployed to the C:\WSTK-3.3\services\demos directory as part of the configuration contain similar characteristics.

For example, both contain a webapp directory and a deployment directory.

The webapp directory for the AddInt Web service contains simply the class required to add the values. The webapp directory for the Dsigdotnet Web service contains the JSP that we ran to access the client portion of the code.

The deployment directories are a little more interesting as they contain both the deployment scripts (WSDD's) for the Web services themselves and the WS-Security settings that are required to secure both the client and server.

The Deploy_server.wsdd file, used to deploy the Dsigdotnet Web service contains two parts. The first specifies the service itself:

  <service name="DSigAddIntService" provider="java:RPC">
    <requestFlow>
      <handler type="wssecurity-receiver"/>
    </requestFlow>
    <responseFlow>
      <handler type="wssecurity-sender"/>
    </responseFlow>
    <parameter name="className" value="AddIntService"/>
    <parameter name="allowedMethods" value="addInt"/>
  </service>

Here, we see the name of the service, the class name that we are going to expose (AddIntService), and the methods that are allowed for this service. In the middle of the declaration, there are also two handlers, wssecurity-receiver and wssecurity-sender. These handlers are responsible for applying the WS-Security-specific information, and are referenced in the second half of the WSDD file itself:

  <handler name="wssecurity-receiver"
 type="java:com.ibm.wstk.axis.handlers.SecurityReceiver">
    <parameter name="configPath"
 value="services/demos/dsigdotnet/deployment/wssecurity-server.xml"/>
    <parameter name="printBefore" value="false"/>
    <parameter name="printAfter" value="false"/>
    <parameter name="logLevel" value=""/>
  </handler>
  <handler name="wssecurity-sender"
 type="java:com.ibm.wstk.axis.handlers.SecuritySender">
    <parameter name="configPath"
 value="services/demos/dsigdotnet/deployment/wssecurity-server.xml"/>
    <parameter name="printBefore" value="false"/>
    <parameter name="printAfter" value="false"/>
    <parameter name="logLevel" value=""/>
</handler>

The handlers, specific to AXIS, reference the classes within the IBM WSTK and get their configuration from another file in the deployment directory: Wssecurity-server.xml.

Wssecurity-server.xml contains the specific settings for WS-Security. Within the ServerBindingConfig elements of this file, is an entry as follows:

<TrustAnchorList>
       <TrustAnyCertificate/>
</TrustAnchorList>

What this does is allow the Web service to be accessed by any client that signs the request with a valid X.509 certificate. It is possible to alter these settings to specify which certificates can be used to allow or deny access. This will be covered in a future article.

IBM WSTK sample client configuration

The client configuration is a little more involved as it requires us to look at some of the AXIS code used to call the WSE 1.0 Web service.

Again, the client code uses the WSDD deployment descriptors to deploy the service, and these reference a wssecurity-client.xml in the C:\wse-interop\WSTK\X509Signing\Services\dsigdotnet\deployment directory.

This XML configuration file contains the reference to the certificate that will be used to sign the request for the WSE 1.0 Web service.

<RequestSenderBindingConfig>
  <SigningKey>
    <KeyStore type="jks"
              path="c:/wse-interop/JKS/keystore.db"
              storepass="password"/>
    <PrivateKey alias="test" keypass="password"/>
  </SigningKey>
</RequestSenderBindingConfig>

As shown, the KeyStore element indicates that our JKS will be used, and gives the name of the certificate in the store (the alias is test).

One of the main differences between the WSTK client and the .NET client is that the reference to the certificate used to sign the request is encoded in the configuration file here, whereas with the .NET client we displayed the Select Certificate dialog box in order to select a certificate from the Windows store. This is purely a consequence of how the sample clients were written, and it would also be possible to create a selection mechanism for the WSTK sample.

The bulk of the WSTK client code can be found in the Addint.jsp file that we ran earlier. This file is located in C:\wse-interop\WSTK\X509Signing\Services\dsigdotnet\webapp, and gets compiled into the Wstk.war file as part of the configuration. If we take a look at this client file, we can see how it works:

After all of the parameters have been read from the HTTP GET request, the deployment file that contains the reference to the WS-Security settings gets loaded with the following command:

String soapDDFile = new String
(WSTKConstants.WSTK_HOME+"/services/demos/dsigdotnet/deployment/deploy_client.wsdd");

It is of course possible to make this deployment global as we did with the service itself, but this follows along the same lines of the other samples in the WSTK.

After the deployment has been configured, the call is made to the .NET WSE Web service:

Service service = new com.ibm.wstk.axis.client.WSTKService(session);
Call call = (Call) service.createCall();
    
call.setTargetEndpointAddress(new URL
("http://localhost:80/WSEX509Interop/Service1.asmx"));

call.addParameter(new javax.xml.namespace.QName("http://microsoft.com/wse/samples/InteropService", "a"),
 new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema",
 "int"), int.class, javax.xml.rpc.ParameterMode.IN);
call.addParameter(new 
javax.xml.namespace.QName("http://microsoft.com/wse/samples/InteropService",
 "b"), new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"),
 int.class, javax.xml.rpc.ParameterMode.IN);
call.setReturnType(new javax.xml.namespace.Qname
("http://www.w3.org/2001/XMLSchema", "int"), int.class);
call.setUseSOAPAction(true);    call.setSOAPActionURI("http://microsoft.com/wse/samples/InteropService/AddInt");
call.setOperationName(new javax.xml.namespace.Qname
("http://microsoft.com/wse/samples/InteropService", "AddInt"));
   
ret = (Integer)call.invoke( new Object[] {aValue,bValue});

As you can see in the previous code, the call is generated using commands from the AXIS libraries (although the initial service is WSTK-specific). It is very important that the operation name in the previous declaration matches both the Web service namespace for the WSE Web service and the service name in the Deploy_client.wsdd deployment file. If either of these are not the same, then the call may not work or may not be signed by the AXIS handlers.

The Web service published through the WSTK is called using a similar set of commands:

Service service = new com.ibm.wstk.axis.client.WSTKService(session);
Call call = (Call) service.createCall();
    
call.setTargetEndpointAddress(new URL
("http://localhost:8080/wstk/dsigdotnet/services/DSigAddIntService"));

call.addParameter(new javax.xml.namespace.QName("", "in0"), new
 javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"),
 int.class, javax.xml.rpc.ParameterMode.IN);
call.addParameter(new javax.xml.namespace.QName("", "in1"), new
 javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"),
 int.class, javax.xml.rpc.ParameterMode.IN);
call.setReturnType(new javax.xml.namespace.QName("http://www.w3.org/2001/XMLSchema", "int"),
 int.class);
call.setUseSOAPAction(true);
call.setSOAPActionURI("");
call.setOperationName(new javax.xml.namespace.Qname
("http://localhost:8080/wstk/dsigdotnet/services/DSigAddIntService", "addInt"));
   
ret2 = (Integer)call.invoke( new Object[] {aValue,bValue});

WSE sample client configuration

The configuration for the WSE Sample Client is mostly done in code, although as with the IBM WSTK sample, these settings could be moved to the a Web.config file if required.

In order to call the IBM WSTK Web service, the WSDL.exe tool generates a proxy class. (For IBM WSTK users, the code in the Addint.jsp described previously was also created using a similar method with the WSDL2JAVA tool in the IBM WSTK).

The WSDL.exe tool created the WSTKProxy.cs file that can be found in the C:\wse-interop\WSTK\X509Signing\dotNETClient directory. As with the generic WSE samples, this proxy file was modified to extend WebServicesClientProtocol from the Microsoft.Web.Services namespace, and adjusted to contain the localhost:8080 reference to the Apache Tomcat installation. A similar proxy file (WSEProxy.cs) was also created for the WSE Web service.

The main class for the .NET client, Client.cs contains the required calls for both the WSE and IBM WSTK Web services.

WSEProxy wp = new WSEProxy();
WSTKProxy ip = new WSTKProxy();
            
SoapContext wpReqContext = wp.RequestSoapContext;
SoapContext ipReqContext = ip.RequestSoapContext;

X509SecurityToken token = GetSecurityToken("");
if (token == null)
     throw new ApplicationException("No key provided for signature.");

wpReqContext.Security.Tokens.Add(token);
wpReqContext.Security.Elements.Add(new Signature(token));

ipReqContext.Security.Tokens.Add(token);
ipReqContext.Security.Elements.Add(new Signature(token));
            
ipReqContext.Path.MustUnderstand = false;

Console.WriteLine("Calling the WSE 1.0 X509 Service...");
Console.WriteLine(wp.AddInt(argA,argB));

Console.WriteLine("Calling the IBM WSTK X509 Service...");
Console.WriteLine(ip.addInt(argA,argB));

These calls should look familiar to anyone who has run any of the sample code that comes with WSE 1.0. One addition made is the following line:

ipReqContext.Path.MustUnderstand = false;

By default, the WSRP header contains a MustUnderstand=1 SOAP header, which works fine with WSE-based Web services, but throws an exception when trying to call an IBM WSTK Web service (this part of the specification may not have been implemented yet). To get around this problem, this line of code removes the requirement for the Web service to understand the header for the Path (a MustUnderstand = 1 still exists for the WS-Security section, however).

WSE sample Web service configuration

The WSE Web service itself is again very similar to the default samples, with the main portion of the exposed method located in the Service1.asmx.cs file, in the c:\wse-interop\dotNETWebService directory.

It is important to notice that the Web service namespace on this class is attributed as follows:

[WebService(Namespace="http://microsoft.com/wse/samples/InteropService")]

As we saw in the previous section, this namespace is used as a reference from the IBM WSTK client and associated deployment descriptors. The AddInt class itself looks as follows:

        [WebMethod]
        public int AddInt(int a, int b)
        {
            SoapContext requestContext = HttpSoapContext.RequestContext;
            if (requestContext == null)
                throw new ApplicationException("Only SOAP requests are permitted.");

            if ( !IsValid(requestContext) )
            {
                throw new SoapException(
"The security information supplied was not valid.",
                    new System.Xml.XmlQualifiedName("Bad.Security",
 "http://microsoft.com/wse/samples/InteropService"));
            }

            return a+b;
        }

As shown here, we check in code—whether or not the request from the client has been signed—with an IsValid method, also in this class.

Using the SOAP Trace Utility to Examine the Results

This article outlines some initial samples for showing WS-Security interoperability between WSE and the IBM WSTK. If you are like me however, you may have a burning desire to know what information is being sent underneath the covers.

To enable this, we can use the SOAP Trace Utility that comes as part of the Microsoft SOAP Toolkit 3.0 (the SOAP Toolkit actually provides SOAP and Web Service functionality for non-.NET-based applications). Download the SOAP Toolkit 3.0.

Once the SOAP Toolkit is installed, the Trace Utility that ships with the toolkit can be configured to listen on one port and redirect to another. Doing this, however, requires some slight changes in the configuration of these samples, which is outlined below.

Using the SOAP Trace Utility with WSE and IBM WSTK

To enable the SOAP Trace Utility to trap calls between WSE and IBM WSTK

  1. Open the Trace Utility. Create two new formatted traces (on the File menu, click New Formatted Trace). One of the traces should listen on port 8081 and redirect to port 8080. The other trace should listen on port 81 and redirect to port 80.
  2. Edit the Deploy.bat files in C:\wse-interop\WSTK\X509Signing\Services\dsigdotnet\deployment and C:\wse-interop\WSTK\X509Signing\Services\addint\deployment to reference –p8081 instead of –p8080.
  3. Edit the Addint.jsp file (in C:\wse-interop\WSTK\X509Signing\Services\dsigdotnet\webapp). Replace each occurrence of localhost:80 with localhost:81, and each occurrence of localhost:8080 with localhost:8081.
  4. Edit WSEProxy.cs and WSTKProxy.cs in the C:\wse-interop\WSTK\X509Signing\dotNETClient directory. Replace each occurrence of localhost:80 in WSEProxy.cs with localhost:81, and each occurrence of localhost:8080 with localhost:8081 in WSTKProxy.cs.
  5. Rebuild the sample code, and re-deploy the IBM WSTK Services as described earlier.

Conclusion

This article provides insight and a working code sample to show how WS-Security can be used to apply X.509 signatures to requests between Web services based on Web Services Enhancements 1.0 for Microsoft .NET, and Web services based on the Java platform using IBM WSTK 3.3.2. This can help to provide a way of ensuring that Web service requests achieve end-to-end security in both applications and services.

In future articles, I'll show how to build on this sample code with more operations and specifications as they are released. Part 2 covers WSE and Java interoperability using GLUE Professional 4.0.1 from The Mind Electric to enable WS-Security functionality for Java.

Show: