Monday, June 6, 2011

Microsoft: Interoperability Between Oracle WebLogic Server 11g and Microsoft.NET WCF 4.0 Using Secure Web Services Part1

Learn how to create secure Web services that support interoperability across Oracle and Microsoft technologies.


Technology Toolbox for this article:

Today, Web services (WS) are the primary model for the development of distributed applications because they were founded over open and mature standards and technologies, such as HTTP and XML.
Since their introduction, Web services have been used to solve many business problems, specifically in the field of integration of heterogeneous systems inside (orchestration) and outside (choreography) organizations.
Major software vendors, such as Oracle and Microsoft, support the Web services specifications in their platforms and frameworks.

Due to the large number of common business scenarios that Web services solutions were facing, Web services specifications started to extend the basic stack of protocols with new standards to support quality of service requirements, such as security, secure conversations, reliability, transactions, and policy enforcement.
One recurring challenge in the integration of heterogeneous applications using Web services is interoperability, because software vendors interpret the Web services specifications in order to adapt them to their platforms, and sometimes this leads to problems. The solution is the use of rules and best practices to implement interoperable Web services, such as WS-I profiles.

A common interoperability scenario found in many organizations is the following:
  • Have the information system running in an Oracle WebLogic Server container
  • Expose the system functionalities using a Web services approach (supporting the WS-* protocol stack)
  • Have the client running in a Microsoft Windows environment and consuming these features in a secure way

This article describes solving the underlying problems of such a scenario using the implementation of Web services with emerging technologies from Oracle and Microsoft, specifically using Oracle WebLogic Server 11g and Microsoft Windows Communication Foundation 4.0.

In order to support the WS-* protocol stack, we need a robust programming model. The Microsoft proposal is Windows Communication Foundation; in the Java world, the proposal is JAX-WS. Oracle WebLogic Server supports JAX-WS as part of the Java EE 5 specification and as the main approach for developing WS solutions in the platform.

For the implementation of the solution in a business scenario, we need a technical foundation for secure services, such as authentication, authorization, confidentiality, and integrity. When talking about security in the Web services world, there are two main classifications: transport-level and message-level security.

Transport-level security refers to securing the connection between the service and the client by relying on the security mechanisms of the underlying transport protocol. A common approach is to use Secure Socket Layer (SSL) to allow two applications to connect over the network to authenticate the other’s identity and to encrypt the data exchanged. The advantage of using transport-level security is that the approach is based on mature and widely adopted standards.

Message-level security is concerned with protecting each Simple Object Access Protocol (SOAP) message regardless of the transportation mechanism used by relying on the WS-Security specification.
The WS-Security specification is an end-to-end mechanism, which means that a message is secure even when the transmission involves several intermediaries. Oracle WebLogic Server implements WS-Security (version 1.0 and 1.1) as well as Username Token Profile (version 1.0 and 1.1), X.509 Token Profile (version 1.0 and 1.1) and Security Assertion Markup Language (SAML) Token Profile (version 1.0 and 1.1). These specifications provide security token propagation, message integrity, and confidentiality in the SOAP message.

In conjunction with WS-Security, we need to use the WS-Policy specification, which defines a framework for allowing Web services to express their security constraints. The main challenge of message-level security is that the approach is maturing and often leads to interoperability problems. The main advantage is that in complex distributed environments with several intermediaries, such as other Web services acting as a router, Enterprise Service Bus (ESB), and workflow engines, the approach is more scalable.

For the implementation of the business case of this article, we’re going to support message-level security by using the WS-Security, WS-Policy, and WS-SecurityPolicy specifications, which provide the foundation for authentication, message content encryption, and digital signing as well as a high level of interoperability.
This article focuses on how to define a WS-Security configuration for the Web service (on the server side running in Oracle WebLogic Server) that can interoperate with the client running in a WCF environment using X.509 certificates to authenticate, sign, and encrypt the SOAP message.

Developing the Server Side of the Solution

In order to focus on how to develop an integration solution using secure Web services standards, our service will be very straightforward by just receiving a string message and returning the same string to the client. Conceptually, this is an echo service. In a real-world application, the Web service implementation will be more complex and consist of invocations to the business objects that are exposing their functionality to the outside world.
Let’s start with the development of the server-side application. Open the Oracle JDeveloper 11g IDE and create a new application (see Figure 1).

olamendy-rest-f1


Figure 1: Create a New Application in Oracle JDeveloper 11g IDE

Click the OK button. Enter the application name, the default package, and the working directory (see Figure 2).

olamendy-rest-f2
Figure 2: Name the Application

Click the Next button. The Name your project page enables you to create a project for our service. (In Oracle JDeveloper, an application comprises several projects.) Enter a descriptive name and a working directory for the project, and select the main technologies for the WS development (see Figure 3).

olamendy-rest-f3
Figure 3: Create a Project

Click the Next button. In the Configure Java Settings page, check the project structure. Finally, click the Finish button (see Figure 4).

olamendy-rest-f4
Figure 4: Configure Java Settings

The next step in the solution is to create a basic JAX-WS Web service named EchoService. The JAX-WS specification is a programming model that allows you to implement Web services by exposing the public methods of Plain Old Java Object (POJO) classes as Web service operations using Java annotations to decorate the behavior of underlying POJO classes.
The first step to create a JAX-WS Web service (JWS) is to. Select the File | New option and click the OK button (see Figure 5).

olamendy-rest-f5
Figure 5: Add a Class
When the Create Java Class window appears, enter the class name and package. Click the OK button to go to the Code Editor in Oracle JDeveloper, where you can implement the business logic of this new class.
Our logic is very straightforward by just returning the same message that the service receives, so we don’t need any business objects. We choose to implement this simple logic directly in the service for illustrative purposes, although it’s remarkable to say that this is not the best practice in real applications (see Figure 6).
olamendy-rest-f6
Figure 6: Code Editor

The next step is to expose this functionality as a Web service by selecting the File | New option and navigating to the Web Services node in the Categories tree. Then select the Java Web Service option (see Figure 7).

olamendy-rest-f7
Figure 7: Expose the Functionality as a Web Service

Click the OK button. The Create Java Web Service wizard appears. Then click the Next button.
In the Select Deployment Platform page, select the Java EE 1.5, with support for JAX-WS Annotations option, and click the Next button (see Figure 8).

olamendy-rest-f8
Figure 8: Enable Support for JAX-WS Annotations

In the Generation Options page, select the component to publish (in this case, it’s the EchoServiceImpl class), and enter information in the Web Service Name and Port Name fields. Click the Next button (Figure 9).

olamendy-rest-f9
Figure 9: Specify the Web Service Name and the Port Name

In the Message Format page, select the SOAP 1.1 Binding and Document/Wrapped options for the SOAP Message Format in order to be interoperable with other Web services implementations.
Oracle WebLogic Server’s Web service container supports SOAP 1.1/1.2. We’re going to use SOAP 1.1 because it is mandated by WS-I Basic Profile 1.1 as the main mechanism of interoperability. Click the Next button (see Figure 10).

olamendy-rest-f10
Figure 10: Select the SOAP 1.1 Binding and Document/Wrapped Options

In the Methods page, select the list of methods (from the Available Methods drop-down list) that the Java Web service will expose. In this case, we have only one method to expose. Click the Next button (see Figure 11).

olamendy-rest-f11
Figure 11: Expose the Method

In the Additional Classes page, we have the option to select supporting classes. In this case, we don’t need any supporting classes. Click the Next button (Figure 12).

olamendy-rest-f12
Figure 12: Select Additional Classes

The Configure Policies page is a very important step in the development of a secure Web service. Along with the WS-Security standards, the WS-Policy and WS-SecurityPolicy standards were introduced in order to define the security policies for Web services.

The WS-Policy specification defines a framework for allowing Web services to advertise their policies and for the clients to specify their policy requirements. WS-SecurityPolicy is an extension of WS-Policy for defining the security policy assertions in particular. These assertions (both conforming to WS-Policy and WS-SecurityPolicy schemas) tell Oracle WebLogic Server how to enforce the protection of the Web services. The assertions also tell to the clients how they need to invoke the Web services. In Oracle WebLogic Server, the assertions take a further step, because they are also used to define transport-level policies as well as the message-level counterpart.

You can use the Configure Policies page to attach one or more policy files to configure security. The first option is to select between OWSM Policies, WLS Policies, and No Policies. Oracle WebLogic Server provides many predefined policies, which reflect common use cases for Web services security and interoperability with other Web services vendors.

OWSM and WLS policies are a policy framework to manage and secure Web services in a consistent way across the organization. Both frameworks are built using the WS-Policy standard.

For each OWSM policy, we can have a WLS policy counterpart. The main advantage of using policy-driven security is that this model separates security concerns from the application logic, so developers can focus on building the application to meet the functional requirements and delegate the security aspects to the framework.

In order to achieve interoperability with Microsoft.NET solutions using WCF 4.0, we need to select an appropriate policy supported by Oracle WebLogic Server. According to joint efforts by Oracle and Microsoft to achieve interoperability between their platforms, the most recommend option is the OWSM policy oracle/wss11_username_token_with_message_protection_service_policy (see Figure 13).

This policy enforces message-level protection (that is, message integrity and message confidentiality) and authentication for inbound SOAP requests in accordance with the WS-Security 1.1 standard.
Messages are protected using WS-Security's Basic 128 suite of symmetric key technologies, specifically RSA key mechanisms for message confidentiality, the SHA-1 hashing algorithm for message integrity, and AES-128 bit encryption.

The keystore is configured through the security configuration. Credentials are provided through the UsernameToken WS-Security SOAP header. Both plain text and digest mechanisms are supported. The credentials are authenticated against the configured identity store.
You can also specify this OWSM policy using the list of counterparts WLS policies, such as Wssp1.2-2007-Wss1.1-UsernameToken-Plain-EncryptedKey-Basic128.xml, Wssp1.2-2007-SignBody.xml and Wssp1.2-2007-EncryptBody.xml.

Basically, the OWSM Policy oracle/wss11_username_token_with_message_protection_service_policy (see Figure 13) allows the Web service consumer to insert the user name and password credentials, signing and encrypting the outgoing SOAP message using a Public Key Infrastructure (PKI) with public/private keys combinations.

Then the Web service decrypts and verifies the credentials and the message integrity. We can apply the policies to endpoints or ports. So, you can have several ports, each one with its proper policy.

olamendy-rest-f13
Figure 13: Configure Policies

Click the Next button and in the Provide Handler Details page, click the Finish button to end the wizard (because we don’t need to configure anything for the service).
After the wizard is closed, you can see that the EchoServiceImpl class is now decorated with the @WebService and @SecurityPolicy annotations (see Figure 14).

olamendy-rest-f14
Figure 14: Classes Decorated with Annotations

As well, we can see that a web.xml file is added with the configurations necessary to access the service from a Web container. Our Web service is exposed as a servlet, which maps to the URL /EchoServiceImplPort. We can also customize this file for our scenario (see Figure 15).

olamendy-rest-f15
Figure 15: Customize the XML File

In order to work with the OWSM policy, oracle/wss11_username_token_with_message_protection_service_policy uses a Public Key Infrastructure, so we need to configure the keystore and credential store for our application server.

The default configuration for the paths to the keystore and credential store is in the jps-config.xml file under the directory WL_DOMAIN/config/fmwconfig, where the WL_DOMAIN variable is the directory of the Oracle WebLogic Server’s domain. The default credential store points to the cwallet.sso file, and the default keystore points to the default-keystore.jks file. Both files are under the directory WL_DOMAIN/config/fmwconfig.

If the default-keystore.jks file doesn’t exist under the directory WL_DOMAIN/config/fmwconfig, we create the store and the Web service’s self-signed certificate by using the keytool command from the Java Development Kit (JDK) installation, as shown in the Listing 1.

As you can see, in this case, we’ve defined the public/private keys combination using the RSA algorithm for the principal weblogic. You can adapt these parameters to your own business situation.
keytool -genkey -alias weblogic –dname “cn=weblogic” -keyalg RSA -keystore default-keystore.jks
-keypass weblogic1 -storepass weblogic1

Listing 1: Create the Store and Certificate


Now, let’s export into a X.509 certificate the Web service’s public key and canonical name, which are stored in the default-keystore.jks file, so they can be used by the client-side solution, as shown in the Listing 2.
keytool -export -alias weblogic -file c:\temp\weblogic.cer -keystore
default-keystore.jks -storepass weblogic1
 
Listing 2: Export the Public Key and Canonical Name
The next step is to add the keystore password (in this case, the password for default-keystore.jks is weblogic1) to the credential store using the WLST command from the EM interface located in the MW_HOME/common/bin, where the MW_HOME variable is the Oracle middleware directory.
In order to use the WLST command, we need to connect to an Oracle WebLogic Server domain. So let’s start the default domain in the embedded Oracle WebLogic Server in Oracle JDeveloper by right-clicking the EchoServiceImpl.java file in the Application Navigator windows. Then select the Run option from the context menu (see Figure 16).

olamendy-rest-f16
Figure 16: Start the Default Domain

Now let’s execute MW_HOME/oracle_common/common/bin/wlst.cmd and the commands shown in Listing 3, which are under the WebLogic Scripting Tool (WSLT) environment. You can adapt these commands to your own business situation by replacing the user weblogic and password weblogic1 for your own configuration.

connect()
createCred(map="oracle.wsm.security", key="keystore-csf-key", user="keystore",password="weblogic1")
createCred(map="oracle.wsm.security", key="sign-csf-key", user="weblogic", password="weblogic1")
createCred(map="oracle.wsm.security", key="enc-csf-key", user="weblogic", password="weblogic1")

Listing 3: Execute Commands Under the WSLT Environment


We have now successfully developed and configured the server side of our solution.
You can access the Web Services Description Language (WSDL) at the following URL, as shown in Figure 17: http://localhost:7101/SecureWebServiceInterAppl-EchoServiceProj-context-root/EchoServiceImplPort?wsdl.

olamendy-rest-f17
Figure 17: Web Services Description Language

It’s recommended that you disable the @SecurityPolicy annotation while generating the client-side artifacts using WCF tools (as shown in the next section) and then later re-enable the @SecurityPolicy annotation to support security. This is recommended due to the fact that security constraints are not well understood by the WCF framework.

Another option is to create and publish a WSDL document and avoid using directly the URL http://localhost:7101/SecureWebServiceInterAppl-EchoServiceProj-context-root/EchoServiceImplPort?wsdl.

Developing the Client Side of the Solution

In order to create the client side of the solution, let’s open Microsoft Visual Studio.NET 2010. Then select the File | New | Project menu option, and navigate in the Installed Templates tree to the Visual C# | Windows node, and select Console Application. Then enter descriptive names for the project, solution, and directory where you’ll store the underlying files (see Figure 18).

olamendy-rest-f18
Figure 18: Enter Names for the Project, Solution, and Directory

The next step is to add references to the necessary assemblies to build a WCF solution. Right-click the References node in the client-side application in the Solution Explorer window. Then select the Add Reference option from the context menu. In the Add Reference window, let’s select the System.Runtime.Serialization and System.ServiceModel assemblies (see Figure 19).

olamendy-rest-f19
Figure 19: Select the System.Runtime.Serialization and System.ServiceModel Assemblies

In order to invoke the Web services’ operations, we need to import the service contract (represented by the WSDL document) into the client’s native representation. The most common way of invoking the Web services’ operations is by using a proxy.

A proxy is a class that exposes an interface that represents the Web services’ contract. If the Web services expose several contracts (over many endpoints), we need to create a proxy for each contract. The proxy provides the same interface as the service and implements the communication mechanisms to transport the messages from the client side to the server side.

One way to generate WCF proxies is by using the SvcUtil.exe command passing as parameters the WSDL document or the message exchange address (MEX), as shown in the Listing 4 and Figure 20.
svcutil.exe  http://localhost:7101/SecureWebServiceInterAppl-EchoServiceProj-context-root/EchoServiceImplPort?wsdl

Listing 4: Run the SvcUtil.exe Command

olamendy-rest-f20
Figure 20: Output from Running the SvcUtil.exe Command

After that, we have encapsulated the underlying communication mechanism with the Web service using the artifacts of WCF.

Now we need to import the X.509 certificate generated by the code in Listing 2 into CurrentUser-Certificates/Personal/Certificates in the Windows Certificates using Microsoft Management Console (MMC), as shown in Figure 21.

olamendy-rest-f21
Figure 21: Import the X.509 Certificate

The next step is to add a configuration file (app.config file) into the project with the necessary information to connect to the Web service using a secure mechanism (see Listing 5).
The first element to configure is the endpoint element (in pink in Listing 5). An endpoint contains three essential elements: the address where the service is located, the contract defining what the service does, and the binding defining how to communicate with the service. An endpoint may contain an optional element named behavior to set up some environment configurations.

In this case, the binding (through the binding and bindingConfiguration attributes of the endpoint element) is tailored to support the main requirements of WS-Security and interoperability with Oracle WebLogic Server (in green in Listing 5).

And finally, the behavior (through the behavior and behaviorConfiguration attributes of the endpoint element) tells how to locate the X.509 certificate (in orange in Listing 5).
<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="EchoServiceImplPortBehavior">
          <clientCredentials>
            <serviceCertificate>
              <defaultCertificate findValue="weblogic" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName"/>
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <bindings>
      <customBinding>
        <binding name="EchoServiceImplPortBinding">
          <security defaultAlgorithmSuite="Basic128"
                    authenticationMode="UserNameForCertificate"
                    requireDerivedKeys="false" securityHeaderLayout="Lax"
                    includeTimestamp="true"
                    keyEntropyMode="CombinedEntropy"
                    messageProtectionOrder="SignBeforeEncrypt"
                    messageSecurityVersion="WSSecurity11WSTrustFebruary2005WSSecureConversation                        
                      February2005WSSecurityPolicy11BasicSecurityProfile10"
                      requireSignatureConfirmation="true">
            <localClientSettings
                  cacheCookies="true"
                  detectReplays="false"
                  replayCacheSize="900000"
                  maxClockSkew="00:05:00"
                  replayWindow="00:05:00"
                  sessionKeyRenewalInterval="10:00:00"
                  sessionKeyRolloverInterval="00:05:00"
                  reconnectTransportOnFailure="true"
                  timestampValidityDuration="00:05:00"
                  cookieRenewalThresholdPercentage="60" />
            <localServiceSettings
                  detectReplays="true"
                  issuedCookieLifetime="10:00:00"
                  maxStatefulNegotiations="128"
                  replayCacheSize="900000"
                  maxClockSkew="00:05:00"
                  negotiationTimeout="00:01:00"
                  replayWindow="00:05:00"
                  inactivityTimeout="00:02:00"
                  sessionKeyRenewalInterval="15:00:00"
                  sessionKeyRolloverInterval="00:05:00"
                  reconnectTransportOnFailure="true"
                  maxPendingSessions="128"
                  maxCachedCookies="1000"
                  timestampValidityDuration="00:05:00" />
            <secureConversationBootstrap />
          </security>
          <textMessageEncoding
              maxReadPoolSize="64"
              maxWritePoolSize="16"
              messageVersion="Soap11"
              writeEncoding="utf-8">
            <readerQuotas
                maxDepth="32"
                maxStringContentLength="8192"
                maxArrayLength="16384"
                maxBytesPerRead="4096"
                maxNameTableCharCount="16384" />
          </textMessageEncoding>
          <httpTransport
              manualAddressing="false"
              maxBufferPoolSize="524288"
              maxReceivedMessageSize="65536"
              allowCookies="false"
              authenticationScheme="Anonymous"
              bypassProxyOnLocal="false"
              hostNameComparisonMode="StrongWildcard"
              keepAliveEnabled="true"
              maxBufferSize="65536"
              proxyAuthenticationScheme="Anonymous"
              realm=""
              transferMode="Buffered"
              unsafeConnectionNtlmAuthentication="false"
              useDefaultWebProxy="true"
          />
        </binding>
      </customBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:7101/SecureWebServiceInterAppl-EchoServiceProj-context-root/EchoServiceImplPort"
                binding="customBinding" bindingConfiguration="EchoServiceImplPortBinding"
                contract="EchoServiceImpl" name="EchoServiceImplPort" behaviorConfiguration="EchoServiceImplPortBehavior">
        <identity>
          <dns value="weblogic"/>
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>
 
Listing 5: Add a Configuration File
In order to use the proxy, we need to first create an instance (in orange in Listing 6) and invoke the Web service’s operations through this instance (in green in Listing 6). Because the security policy we’re working with requires the credentials to be passed through the UsernameToken WS-Security SOAP header, we need to set the credentials using the proxy properties (in blue in Listing 6).
Using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace EchoSvcClientConsAppl
{
    class Program
    {
        static void Main(string[] args)
        {
            EchoServiceImplClient clientProxy = new EchoServiceImplClient();
            clientProxy.ClientCredentials.UserName.UserName = "weblogic";
                       clientProxy.ClientCredentials.UserName.Password = "weblogic1";             
            string output = clientProxy.Echo("Hello world!");
            System.Console.WriteLine("The EchoService output is '"+output+"'");
            System.Console.ReadLine();
        }
    }
}

Listing 6: Create an Instance and Invoke the Web Service’s Operations

Finally, let’s run the console application on the client side. The output resembles what is shown in Figure 22.
olamendy-rest-f22
Figure 22: Output from Running the Console Application

Summary

This article explained how to create secure Web services using WS-* standards, Oracle technologies, such as Oracle JDeveloper 11g and Oracle WebLogic Server, and how to consume the Web service using Microsoft technologies, such as Visual Studio.NET 2010, Microsoft.NET 4.0 Framework, and Windows Communication Foundation 4.0.

Using this approach, you can adapt the sample use case presented in this article for your own business scenario to build robust, enterprise-wide solutions.

No comments :

Post a Comment