Microsoft .NET Client Application
The client application is a Windows Forms application written using Microsoft Visual Studio 2005 with Microsoft WSE 3.0. The first step in creating a client application is to create a Windows Forms application called SignatureGenerationValidationSample.
The following is a screenshot on how to create the Windows Forms application. Once you click OK, the Windows Forms application is created with a default form. Since we are going to invoke the time web service with input data, we will add a text box to enter any random input data and a button to invoke the web service.
We will also add another text box to show the Error message if any (refer to the following screenshot).
Now we should add the Microsoft WSE 3.0 as a reference before we can create the proxy class. You can add the WSE reference by selecting Add Reference from the project and then selecting Microsoft.Web.Services3. Now that WSE3 is added, we can add a web reference to the web service to create the proxy object. It can be added by right-clicking on the Add Web Reference and then entering the WSDL URL and clicking OK to generate the proxy. So far we have:
- Created the Windows Forms application
- Added a reference to WSE3.0
- Created the web service proxy
The next step is to configure and write code to digitally sign the message. Though it is beyond the scope of this book to explain in detail how to configure policy and write custom policy assertions, we will take a high level overview of how Microsoft .NET and WSE 3.0 can be used to sign and verify SOAP messages. With Microsoft .NET 3.0 and WSE 3.0, the web services security can be applied either through:
- Policy configuration for certain frequently-used security configurations
- Custom assertion in combination with policy to perform all other security operations
Since our example focuses only on signing the request and validating the response, we will have to write a custom policy assertion so that SOAP messages can be interpreted both during request and response cycles to perform signature generation and validation. The next step is to write the custom assertion that will:
- Sign the outgoing message
- Verify the incoming message
At a high level, the custom assertion inherits from SecurityPolicyAssertion class and has methods such as CreateClientOutputFilter and CreateClientInputFilter that can be overridden to perform any operation at the client side. In our sample, we have created two new classes called CustomSecurityClientInputFilter and CustomSecurityClientOutputFilter to perform any data processing on request or response. The CustomSecurityClientOutputFilter is derived from SendSecurityFilter and has a method called SecureMessage which can be overridden to digitally sign the message.
The CustomSecurityClientInputFilter is derived from ReceiveSecurityFilter and has a method called ValidateMessageSecurity which can be overridden to validate the signature of the message.
The custom security assertion code would look like:
public override SoapFilter CreateClientOutputFilter( FilterCreationContext context) { // return null; //Encrypt outgoing msg return new CustomSecurityClientOutputFilter(this); } public override SoapFilter CreateClientInputFilter(FilterCreationContext context) { //Decrypt incoming data return new CustomSecurityClientInputFilter(this); }
The CreateClientOutputFilter and CreateClientInputFilter are overwritten to perform the signature generation or validation. The SecureMessage of CustomSecurityClientOutputFilter is invoked during the outbound transaction and the ValidateMessageSecurity of CustomSecurityClientIputFIlter is invoked during the inbound transaction. Once the custom security is written, it should then be added to the policy. To create the policy, you can click on Add New Item and then select the configuration file, then name your policy fi le as WSE3CustomSignaturePolicy.config as shown in the following screen capture:
Once the policy file is added, replace the value with the following code:
<policies xmlns="http://schemas.microsoft.com/wse/2005/06/policy"> <extensions> <extension name="CustomSecurityAssertion" type="SignatureGenerationValidationSample.CustomSecurityAssertion, SignatureGenerationValidationSample" /> </extensions> <policy name="ServicePolicy"> <CustomSecurityAssertion > <clientToken> <x509 storeLocation="CurrentUser" storeName="My" findValue="CN=WSE2QuickStartClient" findType="FindBySubjectDistinguishedName" /> </clientToken> <serviceToken> <x509 storeLocation="LocalMachine" storeName="My" findValue="CN=WSE2QuickStartServer" findType="FindBySubjectDistinguishedName" /> </serviceToken> </CustomSecurityAssertion > </policy> </policies>
The policy information above describes the location of the certifi cate along with a policy name. Once the policy is added, it should be included with the application configuration file so that the policy can be loaded at run time. The app.config can be replaced with the following to include the custom assertion extensions and the policy extensions.
<?xml version="1.0" encoding="utf-8" ?> <configuration> <configSections> <sectionGroup name="applicationSettings" type="System. Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" > <section name="WSSecurtiyClient.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 " requirePermission="false" /> <section name="SignatureGenerationValidationS ample.Properties.Settings" type="System.Configuration. ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> </sectionGroup> <section name="microsoft.web.services3" type="Microsoft.Web. Services3.Configuration.WebServicesConfiguration, Microsoft.Web. Services3, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf38 56ad364e35" /> </configSections> <applicationSettings> <SignatureGenerationValidationSample.Properties.Settings> <setting name="SignatureGenerationValidationSample_ SignAndVerify_TimeService" serializeAs="String"> <value>http://cpd10cisslaksh.coxinc.com:3115/ gateway/services/SID0003021</value> </setting> </SignatureGenerationValidationSample.Properties.Settings> </applicationSettings> <microsoft.web.services3> <policy fileName="..\..\WSE3CustomSignaturePolicy.config" /> </microsoft.web.services3> </configuration>
Now that the policy file is created, application configuration is modified, and custom assertion is written, we can write the code for the button click event to invoke the web service and attach the policy so that the request can be encrypted and response can be decrypted.
The button click code is straightforward. All it does is:
- Gather input from the text boxes
- Instantiate the web service proxy with a WSE-enabled extension
- Attach the service policy to the proxy
- Invoke the method
The code will look like:
string _Inputdata = txtInput.Text; string _Newtime=""; string _error = ""; try { SignAndVerify.TimeServiceWse _Proxy = new SignatureGenerationValidationSample.SignAndVerify. TimeServiceWse(); _Proxy.SetPolicy("ServicePolicy"); _Newtime = _Proxy.getTime(_Inputdata); } catch (Exception ex) { txtError.Text = ""; _error = ex.Message.ToString(); } txtNewTime.Text = _Newtime; txtError.Text = _error;
If the configurations are correct, you will find the new time in the text box when you run the application.
Summary
In this article, I discussed the importance of digital signatures and how Oracle WSM can be leveraged to digitally sign and verify the messages to ensure the integrity of the message. With digital signatures, especially in validating signatures, each application has to maintain the public key information from each business partner and that will eventually become a tedious task by itself. Oracle WSM can help address such issues by centrally managing the keys and the related policy.