Friday, September 30, 2011

Java - Factory Method Concept

Factory method is just a fancy name for a method that instantiates objects. Like a factory, the job of the factory method is to create -- or manufacture -- objects.
Let's consider an example.
Every program needs a way to report errors. Consider the following interface:
Listing 1
public interface Trace {
      // turn on and off debugging
      public void setDebug( boolean debug );
      // write out a debug message
      public void debug( String message );
      // write out an error message
      public void error( String message );
}


Suppose that you've written two implementations. One implementation (Listing 2) writes the messages out to the command line, while another (Listing 3) writes them to a file.
Listing 2
public class FileTrace implements Trace {
          
      private java.io.PrintWriter pw;
      private boolean debug;
      public FileTrace() throws java.io.IOException {
            // a real FileTrace would need to obtain the filename somewhere
            // for the example I'll hardcode it
            pw = new java.io.PrintWriter( new java.io.FileWriter( "c:\trace.log" ) );
      }
      public void setDebug( boolean debug ) {
            this.debug = debug;
      }
      public void debug( String message ) {
            if( debug ) {  // only print if debug is true
                  pw.println( "DEBUG: " + message );
                  pw.flush();
            }
      }
      public void error( String message ) {
            // always print out errors
            pw.println( "ERROR: " + message );
            pw.flush();
      }
}


Listing 3
public class SystemTrace implements Trace {
      private boolean debug;
      public void setDebug( boolean debug ) {
            this.debug = debug;
      }
      public void debug( String message ) {
            if( debug ) {  // only print if debug is true
                  System.out.println( "DEBUG: " + message );
            }
      }
      public void error( String message ) {
            // always print out errors
            System.out.println( "ERROR: " + message );
      }
}


To use either of these classes, you would need to do the following:
Listing 4
//... some code ...
SystemTrace log = new SystemTrace();
//... code ...
log.debug( "entering loog" );
// ... etc ...


Now if you want to change the Trace implementation that your program uses, you'll need to edit each class that instantiates a Trace implementation. Depending upon the number of classes that use Trace, it might take a lot of work for you to make the change. Plus, you want to avoid altering your classes as much as possible.
A factory method lets us be a lot smarter about how our classes obtain Trace implementation instances:
Listing 5
public class TraceFactory {
      public static Trace getTrace() {
            return new SystemTrace();
      }
}


getTrace() is a factory method. Now, whenever you want to obtain a reference to a Trace, you can simply call TraceFactory.getTrace():
Listing 6
//... some code ...
Trace log = TraceFactory.getTrace();
//... code ...
log.debug( "entering loog" );
// ... etc ...


Using a factory method to obtain an instance can save you a lot of work later. In the code above, TraceFactory returns SystemTrace instances. Imagine again that your requirements change and that you need to write your messages out to a file. However, if you use a factory method to obtain your instance, you need to make only one change in one class in order to meet the new requirements. You do not need to make changes in every class that uses Trace. Instead you can simply redefine getTrace():

Implementation:

package pkg;

interface Bicycle {

    //void changeCadence(int newValue);   // wheel revolutions per minute

    //void changeGear(int newValue);

    //void speedUp(int increment);

    void applyBrakes(int decrement);

}


class ACMEBicycle implements Bicycle {

       // remainder of this class implemented as before
    public void applyBrakes(int decrement)
    {
        System.out.println(decrement +  " Breaks applied");
    }
   

    }


class BicycleFactory {
    public static Bicycle getBicycle() {
          return new ACMEBicycle();
    }
}

public class HelloWorld {

    /**
     * @param args
     */
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        //System.out.println("Hello Eclipse!");       
   
        /*
        ACMEBicycle oACMEBicycle;
        oACMEBicycle = new ACMEBicycle();
        oACMEBicycle.applyBrakes(7);
        */
       
   
   
    Bicycle b = BicycleFactory.getBicycle();
    b.applyBrakes(10);
       
    }

}


If we want to have implementation in run time, the we can remove ACMEBicycle class from above code and use  reflection in factory method "getBicycle()". Reflection is a powerful feature of java to call class and it methods as string input.

Wednesday, September 28, 2011

Java Web services: Axis2 WS-Security basics - (Rampart )

WS-Security
WS-Security is a standard for adding security to SOAP Web service message exchanges (see Resources). It uses a SOAP message-header element to attach the security information to messages, in the form of tokens conveying different types of claims (which can include names, identities, keys, groups, privileges, capabilities, and so on) along with encryption and digital-signature information. WS-Security supports multiple formats for tokens, multiple trust domains, multiple signature formats, and multiple encryption technologies, so in most cases the header information needs to include specific format and algorithm identification for each component. The added information can result in a complex structure for the header information, as shown in the (heavily edited) Listing 1 — a sample message with signing and encryption:

Listing 1. Sample message with signing and encryption
<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ...>
 <soap:Header>
  <wsse:Security soap:mustUnderstand="1">
   <wsu:Timestamp wsu:Id="Timestamp-d2e3c4aa-da82-4138-973d-66b596d66b2f">
    <wsu:Created>2006-07-11T21:59:32Z</wsu:Created>
    <wsu:Expires>2006-07-12T06:19:32Z</wsu:Expires>
   </wsu:Timestamp>
   <wsse:BinarySecurityToken ValueType="...-x509-token-profile-1.0#X509v3"
     EncodingType="...-wss-soap-message-security-1.0#Base64Binary"
     xmlns:wsu="...oasis-200401-wss-wssecurity-utility-1.0.xsd"
     wsu:Id="SecurityToken-faa295...">MIIEC56MQswCQY...</wsse:BinarySecurityToken>
   <xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
    <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-1_5" />
    <KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
     <wsse:SecurityTokenReference>
      <wsse:KeyIdentifier ValueType=
       "...#X509SubjectKeyIdentifier">LlYsHyhNnOVA9Aj7...</wsse:KeyIdentifier>
     </wsse:SecurityTokenReference>
    </KeyInfo>
    <xenc:CipherData>
     <xenc:CipherValue>g+A2WJhsoGBKUydZ9Za...</xenc:CipherValue>
    </xenc:CipherData>
    <xenc:ReferenceList>
     <xenc:DataReference URI="#EncryptedContent-ba0556c3-d443-4f34-bcd1-14cbc32cd689" />
    </xenc:ReferenceList>
   </xenc:EncryptedKey>
   <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-c80f735c-62e9-4001-8094-702a4605e429">
      <Transforms>
       <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
      </Transforms>
      <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
      <DigestValue>lKjc5nyLQDZAIu/hZb4B6mLquow=</DigestValue>
     </Reference>
     ...
    </SignedInfo>
    <SignatureValue>TiLmWvlz3mswinLVQn58BgYS0368...</SignatureValue>
    <KeyInfo>
     <wsse:SecurityTokenReference>
      <wsse:Reference URI="#SecurityToken-faa295..."
        ValueType="...-x509-token-profile-1.0#X509v3" />
     </wsse:SecurityTokenReference>
    </KeyInfo>
   </Signature>
  </wsse:Security>
 </soap:Header>
 <soap:Body wsu:Id="Id-8db9ff44-7bef-4737-8091-cdac51a34db8">
  <xenc:EncryptedData Id="EncryptedContent-ba05..."
    Type="http://www.w3.org/2001/04/xmlenc#Content"
    xmlns:xenc="http://www.w3.org/2001/04/xmlenc#">
   <xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc"/>
   <xenc:CipherData>
    <xenc:CipherValue>mirmi0KuFEEI56eu2U3cICz...</xenc:CipherValue>
   </xenc:CipherData>
  </xenc:EncryptedData>
 </soap:Body>
</soap:Envelope>

In this article, you'll see some simple examples of WS-Security headers, with only a single token. The next article in the series will go further in discussing the type of complex structure shown in Listing 1.
WS-Security applies to actual SOAP message exchanges. The service implementation can verify that WS-Security has been properly applied to incoming messages, but clients need to know in advance what they must implement in order to use the service. With the complexity of WS-Security and the number of options supported, it can be difficult just to use a text description for this purpose, and manual configuration of WS-Security handling can cause errors. WS-Policy is a general-purpose structure for specifying extension requirements for Web services, and WS-SecurityPolicy is an extension of WS-Policy specifically for WS-Security support. Together these two standards support describing WS-Security requirements in machine-readable form. The WS-Policy and WS-SecurityPolicy information can be used alone or embedded directly inside Web Services Description Language (WSDL) documents, so that Web service frameworks can configure themselves automatically to a service's requirements.
Introducing Rampart
Rampart is the Axis2 security module, supporting WS-Security, WS-SecurityPolicy, WS-SecureConversation, and WS-Trust. In this article, you'll only see Rampart's WS-Security and WS-SecurityPolicy functions; later articles will give you a look at the other features.
Because Rampart is implemented as a module (actually a pair of modules — rampart.mar and rahas.mar), it plugs into the Axis2 processing framework and does its job by intercepting messages at particular points in the inbound and outbound processing, checking or making changes to the messages as appropriate.
Installing Rampart
Rampart comes with several .jar files (in the distribution's lib directory), along with a pair of .mar module files (in the dist directory). You must add the .jar files to your classpath in order to use Rampart with Axis2, and you must add the .mar files to either your classpath or an Axis2 repository structure.
The easiest way of handling the Rampart .jar and .mar files is to add them into your Axis2 installation. You can just directly copy the .jar files from the Rampart lib directory into your Axis2 lib directory, and the .mar files from the Rampart dist directory into your Axis2 repository/modules directory. (You can also use the Ant build.xml in the Rampart samples directory to copy the files across to your Axis2 installation. Just set the AXIS2_HOME environmental variable to your Axis2 installation directory and run ant from a console open to the Rampart sample directory.)
For many WS-Security features, you also need to add the Bouncy Castle security provider to your JVM security configuration and the Bouncy Castle .jar to your Axis2 installation. This step — not needed for the UsernameToken you'll learn about in this article — is required for other security features to be covered later in the series. Because of patent issues with some of the security algorithms, the Bouncy Castle .jar is a separate download from Rampart (see Resources). Download the appropriate version of the .jar for your Java runtime, and add the .jar to the Axis2 lib directory. You then need to modify your Java installation's security policies to use the Bouncy Castle code by adding a line to the java.security file found in your Java runtime's lib/security directory. Look for the section of the file with several different security.provider lines, and add the following line:
security.provider.99=org.bouncycastle.jce.provider.BouncyCastleProvider

The ordering of the security.provider lines in the file doesn't matter, but it's a good idea to add this after the other lines for predefined security provider implementations.
To use the Rampart code in an Axis2 server installation, you need to create a new axis2.war file, one that includes the added Rampart .jar and .mar files. You can use the Ant build.xml provided in the webapp directory to create axis2.war, provided you make one change: delete the line <exclude name="axis2-codegen*.jar"/> near the end of the file. Then open a console to the Axis2 webapp directory and run ant. After the build.xml runs, you can find the created axis2.war Web application in the Axis2 installation dist directory.
A sample application
The application provided in the example code (see Downloads) is based on one I used in "Axis2 Data Binding" to demonstrate data-binding alternatives for Axis2. For this article and the following ones on Axis2 WS-Security support, I've trimmed it down to just three operations: getBook, addBook, and getBooksByType. To keep things simple, only the Axis Data Binding (ADB) version of the code is provided, but this is not a requirement of working with WS-Security in Axis2 — Rampart implements WS-Security at a level that's independent of the data-binding technique your code uses, so it works with all forms of data binding supported by Axis2.
The root directory of the example code is jws04code. Inside this directory, you'll find Ant build.xml and build.properties files, the library.wsdl file giving the service definition for the example application, a log4j.properties file used to configure client-side logging, and several property-definition XML files (all named XXX-policy-client.xml or XXX-policy-server.xml). The build.properties file configures the operation of the example application. Listing 2 shows the supplied version of this properties file:

Listing 2. Supplied build.properties file
# set axis-home to your Axis2 installation directory
axis-home=PATH_TO_AXIS2_INSTALLATION
# set the connection protocol to be used to access services (http or https)
protocol=http
# set the name of the service host
host-name=localhost
# set the port for accessing the services (change this for monitoring)
host-port=8080
# set the base path for accessing all services on the host
base-path=/axis2/services/
# set the name of the policy file to be used by the client
client-policy=plain-policy-client.xml
# set the name of the policy file to be used by the server
server-policy=plain-policy-server.xml

Before trying out the examples, you need to edit the build.properties file and set the actual path to your Axis2 installation (with Rampart added, as discussed in the preceding section). If you're using a different host or port number for your server, you also need to modify the host-name and host-port values. I'll discuss the remaining values later in this article.
Giving WS-Security a try
WS-Security defines several types of security tokens (including tokens that are part of the core specification, and those defined by profiles as plug-in extensions to the specification), with many options for how the tokens are constructed and used. The point of this article is the configuration and use of Rampart with Axis2, so I'll just use the simplest useful token as an example: the UsernameToken, defined by the UsernameToken profile.
UsernameToken WS-SecurityPolicy
The purpose of a UsernameToken is just to convey username and password information as part of the WS-Security headers. The most basic form of UsernameToken sends both the username and password as plain text. This isn't optimal from a security standpoint (though there's nothing wrong with using this approach over secure connections), but it's easy to see what's being sent, making it a useful starting point.
The WS-SecurityPolicy configuration for a UsernameToken sent as text can be as simple as shown in Listing 3. This policy (shown here with one line split in two to fit the page width — not valid for actual use) consists of a standard WS-Policy wrapper (the elements using the wsp prefix) around a WS-SecurityPolicy UsernameToken assertion.

Listing 3. WS-SecurityPolicy for plain-text UsernameToken
<wsp:Policy wsu:Id="UsernameToken" 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/2004/09/policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:SupportingTokens
          xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
               ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
        </wsp:Policy>
      </sp:SupportingTokens>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

The UsernameToken in Listing 3 uses an IncludeToken attribute to specify the type of message flow that is to include the token — in this case, all message flows that go from the initiator of a request (that is, the client) to the recipient of a request (the server). You could use other defined values for the IncludeToken attribute to specify other uses of the token, but for a UsernameToken this is generally the only value that makes sense.
Applying the policy
WS-Policy and WS-SecurityPolicy are designed to support embedding within WSDL service definitions. References are used to associate a policy to one or more <wsdl:binding>, <wsdl:binding>/<wsdl:operation>, or <wsdl:message> definitions. Axis2 1.4.X implements preliminary handling for policies embedded in WSDL, but as of Axis2 1.4.1 the implementation is not yet robust. This article instead attaches the policies directly to the client and server in order to be compatible with the 1.4.1 code.
Server-side policy handling
For the server side, you apply a policy by adding it into the services.xml configuration file included in each Axis2 .aar service archive. The policy can be added directly as the child of a <service> element to apply to all operations defined by that service. You also need to add a <module> element to services.xml in order to tell Axis2 that the Rampart module must be included in the configuration for the service. Listing 4 is an edited version of the services.xml used by the example application, with the added module reference and policy information shown in bold:

Listing 4. services.xml with embedded policy
<serviceGroup>
  <service name="library-username">
    <messageReceivers>
      <messageReceiver
          class="com.sosnoski.ws.library.adb.LibraryUsernameMessageReceiverInOut"
          mep="http://www.w3.org/ns/wsdl/in-out"/>
    </messageReceivers>
    <parameter
        name="ServiceClass">com.sosnoski.ws.library.adb.LibraryUsernameImpl</parameter>
    <parameter name="useOriginalwsdl">true</parameter>
    <parameter name="modifyUserWSDLPortAddress">true</parameter>
    <operation mep="http://www.w3.org/ns/wsdl/in-out" name="getBook"
        namespace="http://ws.sosnoski.com/library/wsdl">
      <actionMapping>urn:getBook</actionMapping>
      <outputActionMapping>http://.../getBookResponse</outputActionMapping>
    </operation>
    ...

    <module ref="rampart"/>
    <wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
        xmlns:wsu="http://.../oasis-200401-wss-wssecurity-utility-1.0.xsd"
        wsu:Id="UsernameToken">
      <wsp:ExactlyOne>
        <wsp:All>
          <sp:SupportingTokens
              xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
            <wsp:Policy>
              <sp:UsernameToken
                  sp:IncludeToken="http://.../IncludeToken/AlwaysToRecipient">
                <wsp:Policy>
                  <sp:HashPassword/>
                </wsp:Policy>
              </sp:UsernameToken>
            </wsp:Policy>
          </sp:SupportingTokens>

          <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy">
            <ramp:passwordCallbackClass>...PWCBHandler</ramp:passwordCallbackClass>
          </ramp:RampartConfig>

        </wsp:All>
      </wsp:ExactlyOne>
    </wsp:Policy>
  </service>
</serviceGroup>

Regenerating services.xml the easy way

When you use the Axis2 Wsdl2Java tool to generate server-side deployment files it creates a services.xml file as part of the generated artifacts (in the resources directory, under your generation target directory). Any time your WSDL service definition changes, you must regenerate this file, so the need to embed module reference and policy information in the file can be painful. The example code includes a tool to automate this modification to the generated file: the com.sosnoski.ws.MergeServerPolicy class. (Source and binary are in the mergetool directory.) The build.xml file's generate-server target runs this tool to insert the module reference and appropriate policy information into the generated services.xml file each time the server code is generated. You can use the tool for your own projects if you want. It takes the path to the services.xml file as the first command-line parameter, the path to the policy file as the second, and the names of any modules to be added as the remaining command-line parameters.
If you compare the embedded policy in Listing 4 with the basic policy in Listing 3, you'll see one addition — a <ramp:RampartConfig> element. This element provides Rampart-specific extensions to the policy information, in this case giving the name of a class to be used for handling password callbacks. The callback is how your server code can verify the username-and-password combination supplied by the client on a request.
Listing 5 shows the actual implementation of the callback class, as used for the plain-text password. In this case, both the username and password are supplied to the callback, and all the callback needs to do is verify the combination. If the username and password match the expected values, this just returns; otherwise, it throws an exception to indicate the error.

Listing 5. Password callback code
import org.apache.ws.security.WSPasswordCallback;

public class PWCBHandler implements CallbackHandler
{
    public void handle(Callback[] callbacks)
        throws IOException, UnsupportedCallbackException {
        for (int i = 0; i < callbacks.length; i++) {
            WSPasswordCallback pwcb = (WSPasswordCallback)callbacks[i];
            String id = pwcb.getIdentifer();
            if (pwcb.getUsage() == WSPasswordCallback.USERNAME_TOKEN_UNKNOWN) {

                // used when plain-text password in message
                if (!"libuser".equals(id) || !"books".equals(pwcb.getPassword())) {
                    throw new UnsupportedCallbackException(callbacks[i], "check failed");
                }

            }
        }
    }
}

For a real application, you'd naturally want to use some other mechanism (such as a database or an external security mechanism) to verify the username and password combination. The callback technique lets you use any verification technique you want as an extension of the Rampart security handling.
Client-side configuration
To use Rampart for your client code, you first need to have the module available for use with Axis2. You can do this by configuring an Axis2 repository structure for the client, but it's generally easier just to include the rampart.mar module file (and any other modules you need to use) in your classpath. The supplied example uses the classpath approach.
You then need to configure the security policy and any related parameters for the client. The easiest way to handle this configuration is to set values directly on the service stub. Listing 6 shows how the configuration is done in the example code:

Listing 6. Client configuration
/**
     * Load policy file from classpath.
     */
    private static Policy loadPolicy(String name) throws XMLStreamException {
        ClassLoader loader = WebServiceClient.class.getClassLoader();
        InputStream resource = loader.getResourceAsStream(name);
        StAXOMBuilder builder = new StAXOMBuilder(resource);
        return PolicyEngine.getPolicy(builder.getDocumentElement());
    }

    public static void main(String[] args) throws IOException, XMLStreamException {

        // check for required command line parameters
        if (args.length < 4) {
            System.out.println("Usage:\n  java " +
                "com.sosnoski.ws.library.adb.WebServiceClient protocol host port path");
            System.exit(1);
        }

        // create the client stub
        String target = args[0] + "://" + args[1] + ":" + args[2] + args[3];
        System.out.println("Connecting to " + target);
        LibraryUsernameStub stub = new LibraryUsernameStub(target);

        // configure and engage Rampart
        ServiceClient client = stub._getServiceClient();
        Options options = client.getOptions();
        options.setProperty(RampartMessageData.KEY_RAMPART_POLICY,
            loadPolicy("policy.xml"));
        options.setUserName("libuser");
        options.setPassword("books");
        client.engageModule("rampart");

The configuration portion is the final code block in Listing 6. This gets the org.apache.axis2.client.ServiceClient instance from the created stub and sets the policy information (loaded from the classpath) and username/password in the client options. It then engages the Rampart module in the Axis2 configuration used by the client. Once this is done, you can use the stub to access the service just as you would without WS-Security, and Rampart adds the UsernameToken automatically to each request.
Confirming the results
With Ant installed, you can just run ant from a console open to the example code directory to build both client and server code. You can then deploy the created library-username.aar file to your Axis2 server installation (one that includes the Rampart .jars and .mars, of course), and try out the client by entering ant run at the console. If everything is set up correctly, you should see the output shown in Figure 1:

Figure 1. Console output when running application
Console output when running application
Just running the client with the server doesn't show you what's happening, of course. You can use a tool such as TCPMon to act as an intermediary between the client and server and capture the message exchange to see the WS-Security UsernameToken in action (see Resources). To do this, you'd first need to get TCPMon set up and accepting connections from the client on one port, which it then forwards to the server running on a different port (or a different host). You can then edit the build.properties file and change the host-port value to the listening port for TCPMon. If you again enter ant run at the console, you should then see the messages being exchanged. Listing 7 shows a sample client-message capture:

Listing 7. Client message with UsernameToken
<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security xmlns:wsse="...wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      <wsse:UsernameToken xmlns:wsu="...wss-wssecurity-utility-1.0.xsd"
          wsu:Id="UsernameToken-1815911473">
        <wsse:Username>libuser</wsse:Username>
        <wsse:Password Type="...wss-username-token-profile-1.0#PasswordText"
            >books</wsse:Password>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
    <ns2:getBooksByType xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
      <ns2:type>scifi</ns2:type>
    </ns2:getBooksByType>
  </soapenv:Body>
</soapenv:Envelope>

Securing UsernameToken
A basic plain-text UsernameToken doesn't provide much security directly, because both the username and the corresponding password are visible to anyone able to monitor a message. If you use an encrypted communication channel, this isn't a real problem — as long as the channel encryption is solid, no outside party can monitor a message. WS-SecurityPolicy conveniently defines a way to require the use of an encrypted channel, as shown in Listing 8 (again with a line split to fit page width — see the example code package's secure-policy-server.xml file for the real policy):

Listing 8. Policy requiring HTTPS connection
<wsp:Policy wsu:Id="UsernameToken" 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/2004/09/policy">
 <wsp:ExactlyOne>
  <wsp:All>
   <sp:TransportBinding xmlns:sp="http://schemas.xmlsoap.org/ws/2005/07/securitypolicy">
     <wsp:Policy>
      <sp:TransportToken>
        <wsp:Policy>
         <sp:HttpsToken RequireClientCertificate="false"/>
        </wsp:Policy>
      </sp:TransportToken>
     </wsp:Policy>
   </sp:TransportBinding>
   <sp:SupportingTokens
     xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
    <wsp:Policy>
     <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
          ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient"/>
    </wsp:Policy>
   </sp:SupportingTokens>
  </wsp:All>
 </wsp:ExactlyOne>
</wsp:Policy>

The portion of Listing 8 shown in bold is the added part, consisting of a <sp:TransportBinding> element and nested <sp:HttpsToken> element. The <sp:HttpsToken> element says that a secure HTTPS connection must be used in communicating with the service. If you try building the service .aar with this policy (by changing the server-policy value in build.properties to secure-policy-server.xml, and then running ant build-server) and deploying it, you'll see that Rampart enforces this policy requirement, rejecting any normal HTTP connections.
If you want to try out an HTTPS connection to the service you can do so, but you first need to configure your Web server to support HTTPS. (Tomcat has good instructions for this, at /tomcat-docs/ssl-howto.html.) You also need to change the protocol value in build.properties to https, and if you're using a self-signed certificate for the Web server, you need to pass a trust store to the client when running the Ant test target. The supplied build.xml has a commented-out line to do this, so you can just uncomment the line and set the location of the appropriate trust store file on your system.
Another way of making UsernameToken more secure works even over unencrypted links. This method uses a digest value computed over a string made up of two other text values combined with the password. One of the text values, the nonce, is a random value generated by the sender for each request. The other, the created timestamp, is just the time at which the sender created the UsernameToken. Both these values are included in the UsernameToken as plain text. When properly used by both client and server, the combination of these values with the password in the digest makes it possible for the server to verify that the correct password was used when generating the digest, while making it difficult for any outside party to fake a valid password. Listing 9 gives a policy example for using the digest password, followed by an actual capture from a message using the digest password (both reformatted to fit page width — see the hash-policy-client.xml file for the real policy). The differences from the original policy are again shown in bold.

Listing 9. Policy using password digest, and sample message
<wsp:Policy wsu:Id="UsernameToken" 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/2004/09/policy">
  <wsp:ExactlyOne>
    <wsp:All>
      <sp:SupportingTokens
          xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
        <wsp:Policy>
          <sp:UsernameToken sp:IncludeToken="http://docs.oasis-open.org/
ws-sx/ws-securitypolicy/200702/IncludeToken/AlwaysToRecipient">
            <wsp:Policy>
              <sp:HashPassword/>
            </wsp:Policy>
          </sp:UsernameToken>
        </wsp:Policy>
      </sp:SupportingTokens>
    </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>

<?xml version='1.0' encoding='UTF-8'?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Header>
    <wsse:Security xmlns:wsse=".../oasis-200401-wss-wssecurity-secext-1.0.xsd"
        soapenv:mustUnderstand="1">
      <wsse:UsernameToken xmlns:wsu="...wss-wssecurity-utility-1.0.xsd"
          wsu:Id="UsernameToken-1421876889">
        <wsse:Username>libuser</wsse:Username>
        <wsse:Password Type="...wss-username-token-profile-1.0#PasswordDigest"
          >/Wt/2yDdZwa8a5qd7U70hrp29/w=</wsse:Password>
        <wsse:Nonce>4ZQz5ytME/RXfChuKJ03iA==</wsse:Nonce>
        <wsu:Created>2009-03-17T11:20:57.467Z</wsu:Created>
      </wsse:UsernameToken>
    </wsse:Security>
  </soapenv:Header>
  <soapenv:Body>
    <ns2:getBooksByType xmlns:ns2="http://ws.sosnoski.com/library/wsdl">
      <ns2:type>scifi</ns2:type>
    </ns2:getBooksByType>
  </soapenv:Body>
</soapenv:Envelope>

Web services security

http://www.ibm.com/developerworks/webservices/library/ws-sec1/index.html#secure


Date:  25 Feb 2003
Level:  Intermediate 

e-business relies on the exchange of information between business partners over a network. In such a setup, as the information/data travels from the source to the destination, there is always the risk of the data being stolen or modified. The same security risks are applicable to web services transactions. In web services transactions using SOAP, the data are passed between the service invoker and service provider as plain XML, so anyone who intercepts the messages can read the data that are exchanged. In the web services scenario the security aspect is more complicated because:
  • Soap messages can be sent using different transport applications or protocols like HTTP, SMTP, etc., which might have a very high security model to no security model at all. Hence, there is a need for a comprehensive security framework for web services applications, which is common to all types of transport protocols.
  • There could be legitimate intermediaries that might need to access a part or whole of the SOAP message, and even modify the message. Thus the security model must be comprehensive enough to allow such intermediaries.
This article will introduce the various aspects of web services security and will provide step-by-step guidelines on how to write and deploy secure web services applications with existing technologies.
Web services security guidelines
The W3C Web Services Architecture Requirements outlines the following six important security considerations for a comprehensive security framework:
  1. Authentication: guarantees that the service is accessible for anyone with a verified identity.
  2. Authorization: guarantees that the authenticated person has the right to access the service or data.
  3. Confidentiality: guarantees that the data passed between the requester and provider is protected from eavesdroppers.
  4. Integrity: offers that the message was not modified in its path from requestor to provider.
  5. Non-repudiation: guarantees that the sender of the message cannot deny that he/she sent it at a later point in time.
  6. Accessibility: ensures that the service is always accessible and that it is not impaired by attacks, like denial-of-service (DoS), from outside or inside of the system hosting the service.
OASIS is another important standards organization that is developing a formal model/specification for providing more robust and scalable web services security.
Web services today
Web services security is still in its infancy. New standards and applications are being continually developed and deployed. Web services security as of today can be achieved at two levels:
  1. Security at the transport level
    Security at the transport level uses the inbuilt security features of transport technologies like HTTP, IBM WebSphere MQSeries, etc. This article describes how the inbuilt security features of HTTP can be used to secure web services transactions.
  2. Security at the SOAP or messaging level
    This level is currently being extensively researched and specifications are being developed by groups like OASIS. This involves usage of digital signatures, certificates, etc., at the XML document level. This will be discussed in more detail in the second part of this series.
Securing web services with HTTP
Web services transactions over HTTP can be secured by using the following:
  • HTTP basic authorization
  • HTTPS (HTTP Secure) or HTTP with secure socket layer (SSL)
  • HTTP basic authorization + HTTPS
However, HTTP security does not address all of the web services security guidelines, listed earlier. The best possible configuration is to use HTTPS with HTTP basic authorization, which addresses all aspects of web services security except non-repudiation and accessibility. The remainder of this article shows how to configure and develop web services using these approaches. The machine and software configuration we have chosen for demonstrating the examples below are as follows:
Soap client/server: Apache Axis v1.0 Beta 3 (Note: Release version has a bug relating to the use of SSL)
Web server: Apache Jakarta Tomcat v4.0.2
JDK: Sun J2SE v1.4.1
Platform: Microsoft Windows 2000 Professional, Service Pack 3
HTTP basic authorization
HTTP basic authorization (BASIC-AUTH) is a simple mechanism used in HTTP. Using this mechanism we can protect web resources from unauthorized access. To access resources protected using HTTP BASIC-AUTH, a user has to provide a username and password. The web site administrator configures the web server with a list of valid users and resources that a user can access. Since web services invocation over HTTP is the same as accessing a URL (endpoint URL) we can make use of BASIC-AUTH to restrict web services access.
In this section, we will show how to setup BASIC-AUTH for a web service deployed in Apache Axis running on the Apache Jakarta Tomcat Web Server.
Step 1: Writing and deploying a Web Service
We shall begin by writing a simple 'Echo Service'. The Echo Service is a simple Java class as shown in Listing 1.

Listing 1. EchoService.java
public class EchoService {
   public String echoString( String echoStr ) {
      return echoStr;
   }
}

Save the above file as 'EchoService.java'. To deploy the program as a service, just copy it into '%TOMCAT_HOME%\webapps\axis' and rename it as 'EchoService.jws'. That is all there is to it, and you have deployed your first web service. Now your simple web service can be accessed from the URL http://localhost:8080/axis/EchoService.jws?wsdl.
But the service is not yet secure. In order to secure it, create a directory named 'protected' (or any name of your choice) inside '%TOMCAT_HOME%\webapps\axis' and move 'EchoService.jws' into this directory. Now the web service URL becomes http://localhost:8080/axis/protected/EchoService.jws?wsdl.
Step 2: Define user credentials
To add new user credentials, edit 'tomcat-users.xml' in '%TOMCAT_HOME%\conf' and add a new user as shown in Listing 2.

Listing 2. Define new user credentials
<tomcat-users>
  <user name="tomcat" password="tomcat" roles="tomcat,manager" />
  <user name="role1"  password="tomcat" roles="role1"  />
  <user name="both"   password="tomcat" roles="tomcat,role1" />
  <!-- Define new user name and password with the role -->

    <user name="wsuser" password="wspwd" roles="wsuser" />
</tomcat-users>

This step simply defines a new user and the role the user plays. In the next step we will show you how to associate a security constraint to a particular user role.
Step 3: Add a security constraint to the web service URL
In order to add a security constraint, edit 'web.xml' in '%TOMCAT_HOME%\webapps\axis\WEB-INF' and insert the lines shown in Listing 3 immediately before the end of the element <web-app>.

Listing 3. Define security constraint
<Security-constraint>
   <web-resource-collection>
      <web-resource-name>Protected</web-resource-name>
      <!-- specify the directory for restricted web Services application -->
      <url-pattern>/protected/*</url-pattern>
   </web-resource-collection>
   <auth-constraint>
      <!-- specify the role name of the new user added in step 2 -->
      <role-name>wsuser</role-name>
   </web-resource-collection>
   <auth-constraint>
</security-constraint>

<!-- Define the Login Configuration for this Application -->
<login-config>
   <auth-method>BASIC</auth-method>
   <realm-name>Protected Web Services</realm-name>
</login-config>

Restart the Tomcat server so that the settings take effect. Try accessing the WSDL by going to the URL http://localhost:8080/axis/protected/EchoService.jws?wsdl. The browser will request you to authenticate yourself by entering your username and password.
Step 4: Writing a Java client program to access the web service
Listing 4 shows a sample Java client program taken from the Apache Axis User Documentation. We do the following modifications to enable automated client authentication:
  • Change the endpoint/web service address.
  • Set the username and password.

Listing 4. Write the client to invoke the service using BASIC-AUTH
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
  
public class TestClient {
 public static void main(String [] args) {
  try {
    String endpoint = "http://localhost:8080/axis/protected/EchoService.jws";
    Service service = new Service();
    Call    call    = (Call) service.createCall();
    call.setTargetEndpointAddress( new java.net.URL(endpoint) );
    call.setOperationName(new QName("echoString"));
       
    call.setUsername("wsuser");
    call.setPassword("wspwd");

    String ret = (String) call.invoke( new Object[] { "Hello!" } );
    System.out.println("Sent 'Hello!', got '" + ret + "'");
  } catch (Exception e) {
    System.err.println(e.toString());
  }
 }
}

Examination of the SOAP message using TCPMon reveals a new HTTP 'Authorization' header added to the HTTP message as shown in Listing 5. The string after Basic is the BASE64 encoded username and password.

Listing 5. SOAP message snooped by TCPMon
POST /axis/protected/EchoService.jws HTTP/1.0
Host: localhost
Content-Type: text/xml; charset=utf-8
SOAPAction: ""
Content-Length: 1663
Authorization: Basic c2lsdmVyOnNpbHZlcg==

<SOAP-ENV:Envelop>
...
...
</SOAP-ENV:Envelop>

But in the method shown above, the message/data exchanged by SOAP have not been secured. Only the username and password have been encoded. The actual SOAP message is not encrypted and is displayed in plain XML. Anyone who captures the HTTP message, as we have, can read the data/message that is being exchanged, alter it and resend it again. HTTP basic authorization addresses only the authentication and authorization aspects of web services security described above. So we need a more sophisticated mechanism, which addresses other aspects of web services security.
HTTP secure (HTTPS)
Secure socket layer (SSL), is a technology which allows web browsers and web servers to communicate over a secured connection. This means that the data being sent are encrypted by one side, transmitted, and decrypted by the other side before processing. This is a two-way process, meaning that both the server and the browser encrypt all traffic before sending out data.
The following sections show how to developing a secure web services application using Axis and HTTPS.
Step 1: Configuring a web server for SSL
Here we show how to configure Apache Jakarta Tomcat to use SSL. Before you start, ensure you have Java JDK v1.4.0 or above. If not, you need to have Java Secure Socket Extension (JSSE) downloaded and installed on your system.
First, create the SSL certificate which will be used for authenticating and encrypting data. This can be created using the 'keytool' utility provided with J2SE 1.4+. The tool can be found in the '%JAVA_HOME%\bin' directory. Execute the following from the terminal command line:
%JAVA_HOME%\bin\keytool -genkey -alias tomcat -keyalg RSA This command will create a new file, in the home directory of the user under which you run it, named '.keystore'. In Windows 2000, if the user is an Administrator, the file can be found in 'C:\Documents and Settings\Administrator'. After executing this command, you will first be prompted for the keystore password. The default password used by Tomcat is 'changeit' (all lower case), although you can specify a custom password if you like. However for the purpose of this demo we will use the default password.
Second, edit the 'server.xml' file located in the '%TOMCAT_HOME%\conf' directory. Look for a commented connector element defined in XML (Listing 6).

Listing 6. Enable SSL support for Jakarta Apache web server
<!-- Define an SSL HTTP/1.1 Connector on port 8443 -->
<!--
<Connector className="org.apache.catalina.connector.http.HttpConnector"
           port="8443" minProcessors="5" maxProcessors="75"
           enableLookups="true"
           acceptCount="10" debug="0" scheme="https" secure="true">
  <Factory className="org.apache.catalina.net.SSLServerSocketFactory"
             clientAuth="false" protocol="TLS"/>
</Connector>
-->

Remove the comment tags around the Connector element. After completing the above configuration, restart the Apache Tomcat web server. You should now be able to access web applications supported by Apache Tomcat via SSL. For example try, https://localhost:8443 and you should see the usual Tomcat splash page (unless you have modified the ROOT web application). For more detailed information on configuring the web server for SSL, see your web server documentation.
Step 2: Writing and deploying a web service
We use the same 'Echo Service' example used earlier. Copy 'EchoService.jws' into '%TOMCAT_HOME%\webapps\axis'. Access the WSDL URL for the service, but specify the transport protocol as https instead of http and port as 8443 instead of 8080 (port 8443 is the default port for HTTPS in the Apache Jakarta web server). Therefore, the WSDL URL for the 'Echo Service' will be https://localhost:8443/axis/EchoService.jws?wsdl.
Step 3: Creating the SSL certificate for a client
If you are running the server and client on the same machine, then you can use the same certificate that you created for the server in Step 1. However, if the client and the server are running on different machines, then create a new certificate for the client using the 'keytool' utility as explained above in Step 1.
Step 4: Writing a Java client program to access the web Service
Listing 7 shows a sample Java client program taken from the Apache Axis User Documentation. We do the following modifications to enable automated client authentication:
  • Change the endpoint or SOAP web service address to reflect the HTTPS protocol and port.
  • Set the path and filename of the client SSL certificate.

Listing 7. Write the client to invoke the service using SSL
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
  
public class TestClient {
 public static void main(String [] args) {
  try {
    String endpoint = "https://localhost:8443/axis/EchoService.jws";
    System.setProperty("javax.net.ssl.trustStore", 
    "C:\\Documents and Settings\\Administrator\\.keystore");
    Service service = new Service();
    Call    call    = (Call) service.createCall();
    call.setTargetEndpointAddress( new java.net.URL(endpoint) );
    call.setOperationName(new QName("echoString"));

    String ret = (String) call.invoke( new Object[] { "Hello!" } );
    System.out.println("Sent 'Hello!', got '" + ret + "'");
  } catch (Exception e) {
    System.err.println(e.toString());
  }
 }
}

Step 5: Run the client
Compile and run the program and you should be able to see your string echoed back from the server. The difference this time is that the data have been sent encrypted and received encrypted.
HTTP basic authorization + HTTP secure
HTTPS provides excellent security to web services transactions. HTTPS also provides an authorization mechanism for a user by means of signed certificates. However, if a duplicate of the certificate is available, anyone can impersonate the participating agent. So the best form of security can be derived by a hybrid of HTTP BASIC-AUTH and HTTPS. This also satisfies the first four aspects of WS-Security listed earlier as well as providing a better degree of protection from Repudiation. The following steps will explain how to configure your web services application to take advantage of it.
Step 1: Configure web server for HTTPS
Follow Step 1 from the section "HTTP secure" to configure the web server for HTTPS. If you have already configured the server, then it need not be configured again.
Step 2: Write and deploy the web service with BASIC-AUTH
In this section, we will also take the simple 'Echo Service' to demonstrate HTTPS + HTTP BASIC-AUTH. Follow Steps 1 to 3 to write and deploy the web service application from the section "HTTP basic authorization." The WSDL address for the Echo Service is now available at the URL https://localhost:8443/axis/protected/EchoService.jws?wsdl.
Step 3: Creating the SSL certificate for client
Follow Step 3 from the section "HTTP secure" to create an SSL certificate for the client.
Step 4: Writing a Java client program to access the web service
Listing 8 shows a sample Java client program taken from the Apache Axis User Documentation. We do the following modifications to enable automated client authentication:
  • Change the endpoint or SOAP web service address to reflect the HTTPS protocol and port.
  • Set the path and filename of the client SSL certificate.
  • Set the username and password.

Listing 8. Write the client to invoke the service using BASIC-AUTH over SSL
import org.apache.axis.client.Call;
import org.apache.axis.client.Service;
import javax.xml.namespace.QName;
  
public class TestClient {
 public static void main(String [] args) {
  try {
    String endpoint = "https://localhost:8443/axis/EchoService.jws";
    System.setProperty("javax.net.ssl.trustStore", 
    "C:\\Documents and Settings\\Administrator\\.keystore");
    Service service = new Service();
    Call    call    = (Call) service.createCall();
    call.setTargetEndpointAddress( new java.net.URL(endpoint) );
    call.setOperationName(new QName("echoString"));
       
    call.setUsername("wsuser");
    call.setPassword("wspwd");

    String ret = (String) call.invoke( new Object[] { "Hello!" } );
    System.out.println("Sent 'Hello!', got '" + ret + "'");
  } catch (Exception e) {
    System.err.println(e.toString());
  }
 }
}

Step 5: Run the client
Compile and run the program and you should be able to see your string echoed back from the server. The difference this time is that the web service data have been authenticated as well as encrypted.
Summary
The security methods discussed provide simple, but effective, solutions to secure your web services transactions over HTTP. However, a word of caution. As the complexity of web services transactions increases, these methods may become unsuitable. Consider, for example, that the methods discussed above would be unsuitable if the same SOAP messages were exchanged using SMTP (Simple Mail Transfer Protocol). Similarly, the solutions presented above might not be applicable if there were legitimate intermediaries present. In order to address these issues, a comprehensive WS-Security specification is being developed and standardized. The second article in this series will introduce the WS-Security specification and provide a detailed account of how it can be used to take the security of your web services applications to the next level.

Tuesday, September 27, 2011

Security for SOA and Web Services

 Security Standards and Technologies
Is a web services security layer really required? To answer this question, one needs to look into the security concerns and try to address them using existing security technologies. The industry has a set of existing and widely accepted transport-layer security mechanisms, such as SSL (Secure Sockets Layer), TLS (Transport Layer Security). Despite their popularity, SSL and TLS (which is a minor update of SSL) have some limitations when it comes to web services.
 SSL is designed to provide point-to-point security, which is not enough for web services because end-to-end security is required. In a typical web services environment where XML-based business documents are routed through multiple intermediaries, it becomes difficult for those intermediaries to participate in security operations in an integrated fashion.
 SSL-based communication provides security (confidentiality, integrity) at the transport level rather than at the message level. As a result, messages are protected only while in transit on the wire. For example, sensitive data received on SSL channel, once persisted, is not generally protected unless one applies some encryption technology.
 Finally, SSL does not provide element-wise signing and encryption. For example, if there is a large purchase order XML document, and there is a need to sign or encrypt only a credit card element, signing or encrypting only that element with SSL is not possible.
All of these limitations make SSL and TLS unsuitable for most of the security needs of web services. In the last couple of years, this gap has been identified by the industry and considerable effort has been invested to provide a new security architecture to address the needs of SOA. It is important to realize that the new service oriented security architecture must adhere to the essential characteristics of SOA.
Organizations have existing security infrastructures in place, which protect the resources on diverse platforms. The fundamental goal of SOA is to enable the existing infrastructures to interoperate. The solution is to enable a security spanning layer over existing security infrastructures with a SOA.
SOA enables organizations to build a set of reusable security services that can be used by business applications. The resulting reusability ensures consistent security policies across platform with reduced development costs. For example, an authentication function can be offered as service. Due to the distributed nature of SOA, it is important that the standards-based architecture is adopted, which delivers interoperability and lets the infrastructure operate across organizational boundaries. In the last couple of years, much work has been done to create security standards, which are very promising.
Message Security

Message security is about providing message confidentiality, integrity, non-repudiation, and exchanging security credentials between web service client and web service.
WS-Security is an OASIS standard. WS-Security describes enhancements to SOAP messaging to provide message integrity, message confidentiality, and message authentication. WS-Security uses XML Signature to provide message integrity and message authentication and uses XML Encryption to provide confidentiality. WS-Security also provides a general-purpose mechanism for associating security tokens with messages. Examples of security tokens are X.509 certificate, SAML assertion.
XML Encryption is a W3C recommendation. It ensures confidentiality of XML information transfers. XML Encryption allows the parts of an XML document to be encrypted while leaving other parts open. WS-Security provides processing rules for using XML Signature for SOAP messages. JSR 106 (XML Digital Encryption APIs) defines a standard set of APIs for XML digital encryption services.
XML Signature is a W3C recommendation. It ensures message integrity and authentication. WS-Security provides processing rules for using XML Signature for SOAP messages. Signature can be applied over parts of an XML document. JSR 105 (XML Digital Signature APIs) defines a standard set of high-level implementation-independent APIs for XML digital signature services.
As mentioned above, in B2B applications, sometimes there is a need for message non-repudiation. Non-repudiation is required due to malicious senders who can later disavow having created and sent a particular message. Resolving non-repudiation issue requires message authentication and sender authentication simultaneously. This can be achieved by using XML Signature for message authentication and SSL-based sender authentication.

WS-Security

WS-Security (Web Services Security, short WSS) is a flexible and feature-rich extension to SOAP to apply security to web services.
WS-Security describes three main mechanisms
  • How to sign SOAP messages to assure integrity.
  • How to encrypt SOAP messages to assure confidentiality.
  • How to attach security tokens to ascertain the sender's identity .
The specification allows a variety of signature formats, encryption algorithms and multiple trust domains, and is open to various security token models, such as:
  • X.509 certificates
  • Kerberos tickets
  • UserID/Password credentials
  • SAML-Assertion
  • Custom defined token


WS-Security incorporates security features in the header of a SOAP message, working in the application layer.


Transport Layer Security (Without WS-Security)

The typical SOAP use case with a communication between trusted peers (using HTTPS) does not need WS-Security at all. It is described in Alternative, and reduces complexity and improves performance.


End-to-end security

If a SOAP intermediary is required, and the intermediary is not or less trusted, messages need to be signed and optionally encrypted. This might be the case of an application level proxy at a network perimeter, that will terminate TCP connections.

Non-Repudiation

The standard method for non-repudiation is to write transactions to an audit trail, that is subject to specific security safeguards. However, if the audit trail is not sufficient, digital signatures may provide a better method to enforce non-repudiation. WS-Security can provide this.


Performance

WS-Security adds significant overhead to SOAP-processing due to the increased size of the message on the wire, XML and cryptographic processing, requiring faster CPUs and more memory and bandwidth.
An evaluation in 2005 measured 25 types of SOAP messages of different size and complexity processed by WSS4J with both WS-Security and WS-SecureConversation on a Pentium 4/2,8 GHz CPU. Some findings were:
  • Encryption was faster than signing
  • Encryption and signing together were 2-7 times slower than signing alone and produced significantly bigger documents.
  • Depending on the type of message, WS-SecureConversation either made no difference or reduced processing time by half in the best case.
  • It took less than 10 milliseconds to sign or encrypt up to an array of 100 kilo bytes, but it took about 100~200 to perform the security operations for SOAP.
Another benchmark in 2006 resulted in this comparison:

Security Mechanism Messages/second
WS-Security (X.509) XML Signature & Encryption 352
WS-SecureConversation XML Signature & Encryption 798
Transport Layer Security

Wednesday, September 21, 2011

Axis2 vs JAX-WS RI vs Apache CXF vs Spring-ws

we were given the daunting task to evaluate a web services engine or soap engine or ws stack… many names but underlying tools are the same (one from wsdl to java and other from java to wsdl).. btw we were researching on stacks for java based development… but other ppl from peer technologies can also read thru… after all ws is about language independent services ;)
pre-requisites:
1. we needed xmlbeans badly as that is something which can go nearest to xml representation in xsd and useful for some data type conversion support… so xmlbeans have support that no other binding has.. it was part of weblogic services stack until 8.x i heard until BEA has thought wise and gave it as seperate product.
2. as our app was an existing java application which needed to be service enablising … we needed a very mature and easy to user services stack along with all the buzz words from architecture group.. like WS-I* support… it is a set of standards set by interoperability( will call as I16 from now on), i dont have a single neuron size idea why we would be needing that support in the first place.
3. as our architecture group pitched in.. they brought along lot of web services buzz words… ESB, WS-I16, soap station… synchronous jms ;) .. stay amazed.. we have a set of great ppl.
4. we also needed to have spring as core part of implementation of these services.. so out of the box support would be greatly appreciated.
so then we started to evaluate all the possible frameworks or service stacks…
axis was easy to use and generate stubs.. first tried with AAR file based deployement.  then with codegen and axis2 plugins available in eclipse.. after few days of experimenting we were able to follow the good documentation of axis2 and come up with a small example of spring based service, top down development(that was pretty slick with even the build file by axis2) and then bottom up.
cxf was pretty easy to use with spring.. the driving force for us was spring.. but one of the fellow evaluators started conveying doubts on… no good documentation and not many people are out there who went thru the  pains and have posted the solutions to all the commonly faced problems.. sometimes its not how gud the framework is that decides its maturity.. its how good the support forums and user base is .. that decides the maturity factor. even axis2 wud have had the issue if not for the extensive documentation and support forums.
spring-ws seemed the easiest for us.. .still if u have some small internal services which are already based on spring.. go ahead with spring-ws. only issue was spring-ws was still in 1.0 stage… which is scary.
Then comes the almightier JAX-WS… we had a new soa consultant who is supposed to have had lot of experience with web services… when we were having discussion.. he asked why you are considering axis2? we said.. ” thats the recommended stack from our arch group” (sometimes we have to satisfy few people even though you are draining an entire ocean to find a crab.. bad proverb) his opinion was “you need your services to be vendor neutral… so if you are not going to use the hot deployement feature of axis2… there is no use in going with axis2. jax-ws is the spec from industry “sun” and it is the best available” he was not aware that we are only towards “XMLBeans binding”… eventually while reading thru jax-ws documentation.. i think it supports only jaxb and no other binding.. is it true?
Axis2
JAX-WS RI
Apache
CXF
Spring-
WS
Framework maturity
Quite mature
Open standard and mature
Mature
1.0 is the latest release available
Binding support
ABD,JIBX,XMLBeans (is part of
distribution and has flag to generate javacode out
of xsd’s)
Only JAXB?
JAXB 2.0, Aegis, XMLBeans. (xmlbeans are not
supported out of the box like axis2)
JAXB, Castor, XMLBeans, JiBX, and XStream (similiarly no out of
the box support, not part of distribution or tool)
Core
Axiom
Java Annotations
Xfire+..
Spring
Top down support
Very good
Not so good
Not so good
Very good
Bottom up support
Very Good
Very Good (annotations)
Very Good (Spring)
Very good
XMLBeans support
Out of the box support
NA
It says it supports, but no easy documentation or flags to
generate java classes from xsd.
NA
Number of frustrated people met
Axis1 was bad in terms of performance and Many ppl are not happu because of
.net interoperability issue.
Less number of frustrated people.
Number of happy people
moderate
Many as sun spec is Jax-ws
moderate
NA J
Actual interoperability support (.net and java)
good
Metro (joint project by sun with Microsoft)
WS-I full support but not sure
NA
0

Tuesday, September 20, 2011

Eclipse WTP Tutorials - Creating Bottom Up Web Service via Apache Axis2

http://www.eclipse.org/webtools/community/tutorials/BottomUpAxis2WebService/bu_tutorial.html

Tutorial 1: Creating Web Services in Eclipse (Bottom Up)

(Please check also the update Tutorial with Helios here)
The purpose of these series Tutorial (updated with eclipse galileo) is to introduce tools needed, setup and initial guidelines for Service Oriented Applications.
Since there are many tutorials out there, this text will provide urls that point to each step and fill any gap between them. Web Services, Service Orchestration, Enterprise Service Buses and Business Rules Engine will be explored during these tutorials. The tool that we will mainly use as development platform is Eclipse. One might debate for NetBeans 6 (i.e. for a fair comparison see http://www.javaworld.com/javaworld/jw-03-2008/jw-03-java-ides0308.html?page=4). It's plugin ecosystem, OSGi based architecture makes it though my personal favorite choice.
We will start by just downloading the latest version of Eclipse. Download the EE bundle. Although one could use Yoxos and create a custom Eclipse download, we will just use Eclipse's update feature and install things as we go. You will need also a JDK. During this tutorial jdk1.6.0_12 is used.

These tutorials use Eclipse 3.5.0 (galileo). Just unzip your Eclipse file on your hard disk. As a rule of thumb, try to have different Eclipse installations for different needs, thus making your environment lighter. I.e. don't load your Java EE Eclipse with C/C++ plugins. (I have it under C:\eclipse-jee-galileo-win32)
Creating Bottom Up web services is the most simpler way, since you just make your POJO and you let to Eclipse the hard work to create WSDL, deploy service, etc.
Before starting your web services development, we need Apache Tomcat. So, download it and install it on your machine. During this tutorial we have used Apache Tomcat 6.0.18 Server. I used Windows Service Installer (since during this tutorial is made on Windows Vista. Linux would be a much more serious choice! ).
To configure your Apache Server in Eclipse,
·        Open Window -> Preferences -> Server -> Runtime Environments to create a Tomcat installed runtime.
·        Click on Add... to open the New Server Runtime dialog, then select your runtime under Apache (Apache 6.0 from the list). “Create a new local server” must be checked when adding the Apache Tomcat runtime environment. (This is usefull so not to mess up your actual web services with your web services that you are developing and testing)
·        Put your Tomcat installation dir C:\Program Files\Apache Software Foundation\Tomcat 6.0 and finish.
·        In the Servers panel, you will see the Tomcat server Stopped. In the Project Explorer view, a Server configuration will appear.
·        If you run the Server you might encounter an error if your Tomcat is already running. So you must configure different ports for your installation , otherwise you must stop your Tomcat server while you are developing and testing your web services. If you double click the server, the local configuration will appear. Change the ports as you wish and the Right Click the server Icon and select Start to start the server
 
 Before continuing we will need Apache Axis( an implementation of the SOAP). Download it from here. (This tutorial uses axis2-1.4.1.)
Save it for example on c:\axis2-1.4.1 and point Eclipse WTP to downloaded Axis2 Runtime. Open Window -> Preferences -> Web Services -> Axis2 Preferences and put there the path of Axis2.
On preferences check Generate an interface for the skeleton and Click OK
A nice Creating Bottom Up Web Service tutorial could be found here with similar action. However in this tutorial things are updated.
Create a project "ResourceA" with the support of Axis2 features. Open File -> New -> Other... -> Web -> Dynamic Web Project
 

 On the configuration click Modify..and check the Axis2 Web Services, click OK and Finish
 
Create a package named pkg (Right click on Java Resources ->New->Package) and a class name MyService (Right click on Java Resources->New->Class) . At the end you will have something like the following:
 

 Write the small Java code:
public class MyService {
public MyService() {
}
public Boolean Configure(String param, String val){
return true;
}
public Boolean StartMe(){
return true;
}
public Boolean StopMe(){
return true;
}
public String getStatus(){
return "No status available!";
}
}
Save it and Select the MyService.java file Right click and (down on the menu) Web Services -> Create Web Service
On the window that appears just click the Web Service Run Time and on the dialog select Apache Axis2

Click Next and leave the default services.xml.
Click Next and if prompted Start the server (remember here the ports otherwise the server will not run!)
The ResourceA now is deployed and start in our Tomcat server (remember the Eclipse copy of Tomcat (listens on 8081) not your system Tomcat (listens on 8080))
   

Now if you Select the ResourceA project, right-click and select Run -> Run As -> Run on Server you will go to http://localhost:8081/ResourceA/ which is a not found. (I don’t know why yet.Is this a bug?)
Just change it with the correct http://localhost:8081/ResourceA/axis2-web/index.jsp . You will get the home page:
 

Click on services. Check that your web service is Active. Check also the available Operations:
 

 If you click on the MyService link you will get the WSDL of your service (http://localhost:8081/ResourceA/services/MyService?wsdl)
 Copy this link on your clipboard.

Go to menu Run-> Launch the Web Services Explorer, and select from the icons the WSDL


Click on WSDL Main and paste the wsdl address, click Go.
 


The service will open. Just go for ie MyServiceSoap11Binding find the getStatus and click Go. A Soap call will be invoked and the message in the Body of the response will appear.



During this tutorial we created our first Web Service with Eclipse Web Tools Platform. In this tutorial here a Java client is also created that utilizes a web service.
To deploy your service on your Tomcat server, just right click the project ResourceA choose Export->WAR file.

Probe further:

The alternative way of Top-Down can be found in other tutorials. Check also a nice tutorial here.
Here you can find a nice getting started guide with Web Tools Platform.