Securing Web Services with WebLogic Server 9.2
Pages: 1, 2, 3

Add confidentiality to the service

We will now look at adding message confidentiality. This means we would like our message (SOAP body) encrypted between client and server. The basic procedure is the same as it was for adding message integrity: annotate the service and regenerate, and then update the client.

Open HelloWorldService.java in WTP. Add the following highlighted annotation:

@Policies({

        @Policy(uri="policy:Sign.xml")
                        
,

        @Policy(uri="policy:Encrypt.xml")

})



                      

(Do not forget to add the comma after the Sign.xml annotation.)

This annotation specifies that we would like the client and server to use encryption. By default, encryption is two-way (that is from client to server and server back to client). If only one-way encryption was required, we could have added an optional direction attribute to the annotation to handle this.

We now need to rebuild the service. From the command shell window, run the ant command. As before, you should see a BUILD SUCCESSFUL message.

Now, to update the client. First, obtain and save the WSDL file from the browser as you did in the previous section. Open it with an editor. You should notice a new element: wssp:Confidentiality. This is a hint to the client that encryption should be used. Also note the inclusion of the Encypt.xml policy, as evidenced by the following:

<wsp:Policy s0:Id="Encrypt.xml"> 

...

</wsp:Policy> 



... 



  <portType name="HelloWorldPortType" wsp:PolicyURIs="#Sign.xml #Encrypt.xml"> 

    .. 

  </portType> 

Since the WSDL file was regenerated by the new deployment, we need to update the port number for the monitor again. Near the bottom of the WSDL file, locate the line:

<s2:address location="http://localhost:7001/HelloWorldService/HelloWorldService"/>

Change the port number to 7002 as follows:

<s2:address location="http://localhost: 7002/HelloWorldService/HelloWorldService"/>

Save and close the WSDL file. Now, in the command shell, run command ant -buildfile gen-client.xml. You should see a BUILD SUCCESSFUL message. The client proxy has been updated.

What next? Well, there is actually no need for any other changes. The client does not need any code added to it to cause the messages to be encrypted. All the encryption work will be provided by the client proxy. This is a major advantage to using the Web services security mechanisms; not a single line of encryption code has to be written by any developers!

Run the HelloWorldClient. You should see the usual greeting response. What changed? At the outset, nothing much. However, examine the TCP/IP monitor. You should see that both the request and the response have been encrypted; you should not be able to locate the <name> element that you could earlier. In its place is a <CipherData> element, along with some encrypted text. Note that only the message body (the name element for the request and the return element for the response) have been encrypted; all the message headers have been left unencrypted. Also, note that a ns1:EncryptedKey element has been added to the security header ( wsse:Security).

Message confidentiality has been added to the service!

Add authentication to the service

Next we can add an authorization mechanism to the Web service. Simply put, we can force the client to supply a username and password with the SOAP request; if that username and password does not exist inside WebLogic Server's user registry, the server will deny access to the service. This allows a form of access control. Note that this is different from the identity portion of message integrity. Message integrity asserts identity of a client via a certificate; authority concerns itself with the client having the actual authority to invoke the service. If a client attempts to invoke a service without successfully authenticating against the WebLogic Server user registry, the server will deny access to the service.

In this part of the tutorial, we will add a user to the WebLogic Server user registry, and then change the service to force the client to authenticate. We will then test this using the client.

The first step is to create a user in the WebLogic Server user registry. By default, the user registry is an embedded LDAP server that ships with WebLogic Server, and users can be added to it via the WebLogic Server administration console. Make sure the server is running, and use a browser to browse to http://localhost:7001/console. Log in with username weblogic and password password. The administration console will open.

In the Domain Structure pane on the left, click Security Realms. In the right pane, click myrealm. This myrealm represents WebLogic Server's current security configuration. We will add a test user to this configuration. Click the Users and Groups tab. Click the New button.

For the Name, enter suzie. For the Description, enter An authenticated Web service user. For the Password and Confirm Password fields, enter munchkin. Click OK.

We have created a new user in WebLogic Server's user registry. We can now edit the service to require that all clients authenticate themselves by presenting a username/password (which should hopefully match a user in the registry). In WTP, open HelloWorldService.java and add the following highlighted annotation.

@Policies({

        @Policy(uri="policy:Sign.xml"),

        @Policy(uri="policy:Encrypt.xml")
                        
,

        @Policy(uri="policy:Auth.xml"

                ,direction=Policy.Direction.inbound)

})



                      

The new annotation specifies that an authorization policy should be enforced but only for inbound traffic. (It would not make much sense for the server to have to authenticate back to the client in this example.)

Save the file. There should be no errors. We can now build and deploy the service. From the command shell window, run the ant command. As before, you should see a BUILD SUCCESSFUL message.

Now that the service has been regenerated, we also have to regenerate the client proxy as we did before. Obtain and save the WSDL file from the browser as you did in the previous section. Open it with an editor. A new element wssp:Identity should appear. This is a hint to the client that a username and password should be sent when the service is invoked. Also note the inclusion of the new Auth.xml policy, as evidenced by the following:

<wsp:Policy s0:Id="Auth.xml"> 

    ... 

</wsp:Policy> 



...



<input>

  <s2:body parts="parameters" use="literal"/>

    <wsp:Policy>

      <wsp:PolicyReference URI="#Auth.xml"/>

    </wsp:Policy>

</input>

As before, since the WSDL file was regenerated by the new deployment, we need to update the port number for the monitor. Near the bottom of the WSDL file, locate the line:

<s2:address location="http://localhost:7001/HelloWorldService/HelloWorldService"/>

Change the port number to 7002 as follows:

<s2:address location="http://localhost: 7002/HelloWorldService/HelloWorldService"/>

Save and close the WSDL file. Now, in the command shell, run the command ant -buildfile gen-client.xml. You should see a BUILD SUCCESSFUL message. The client proxy has been updated.

Back in WTP, refresh the WSTest project. Run the HelloWorldClient class. What happens?

javax.xml.rpc.soap.SOAPFaultException: Unable to add security token for identity

Our client is attempting to invoke the service but is not providing any authorization credentials. We need to change the client code so that it invokes the service with that suzie/munchkin username/password that we created earlier. Let's do this now; add the following highlighted code to the main method in HelloWorldClient.java:

  stub._setProperty(

    WSSecurityContext.CREDENTIAL_PROVIDER_LIST,

    credProviders);



   
                        
String username = "suzie";

  String password = "munchkin";

  cp = new ClientUNTCredentialProvider(username.getBytes(), 

        password.getBytes());

  credProviders.add(cp);

  

 

  stub._setProperty(

                      

Run the code. The usual greeting message should now be returned. We now know that the client has been forced to add credentials before it could invoke the service. Check the monitor and examine the request. There should be a new section:

<wsse:UsernameToken>

  <wsse:Username>suzie</wsse:Username>

  <wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/

                oasis-200401-wss-username-token-profile-1.0#PasswordText">munchkin</wsse:Password>

</wsse:UsernameToken>

These are indeed the credentials that we have supplied. Note that these credentials are being transmitted in plain text. The WS-Security spec does not talk about encrypting user credentials; it is recommended that transport layer security (that is, securing the entire TCP/IP socket) be used here.

We have successfully added authentication to our Web service!

An Eye Toward the Future: Configuring Security in WebLogic Server 10

WebLogic Server 10 was recently released. What does this mean to your existing secured Web services? Fortunately, not much. Services deploy and run unchanged in version 10. Client code will, however, need to be regenerated using the version 10 client API. Additionally, WebLogic Server 10 has added support for WS-SecurityPolicy 1.2, and now supports WS-Security 1.1. (WebLogic Server 9.2 supports WS-Security 1.0.)

The significance of the inclusion of the WS-SecurityPolicy 1.2 specification is that you can now create "standardized" security policy files versus BEA proprietary ones. WebLogic Server 9.2, which was released before the WS-SecurityPolicy specification had been released, uses security policy files written under an old version of the WS-Policy specification using a proprietary BEA schema for security policy.

Which type of policy files should you use? BEA recommends you use the WS-SecurityPolicy standard policy files in place of their proprietary policy files. Actually, both types of policy files are supported in version 10, but they are incompatible, so only one type can be used within a given Web service.

However, before you rush out and migrate your WebLogic Server 9.2 policy files to the new standard, keep in mind WS-SecurityPolicy has some limitations, since it was available only in draft form (and still is) when BEA implemented it. Specifically, if you require element-level digital signatures and/or encryption (that is, you don't want to digitally sign and/or encrypt the entire body of the message) or you require SAML 1.1, then you still have to use the proprietary, BEA WebLogic 9.2-style policies.

In terms of WS-Security, even though WebLogic Server 10 supports WS-Security 1.1, BEA still recommends you use WS-Security 1.0 policies for interoperability. You should use WS-Security 1.1 policies only if you have stronger security requirements. Furthermore, WS-Security 1.1 is supported only by using the new, WS-SecurityPolicy 1.2 policy files.

Conclusion

In this article, we have discussed the three facets of Web services security: message integrity, message confidentiality, and authentication. We have seen that coding a "secure" Web service with these assets is quite simple; merely annotating the Web service code with the appropriate annotations is all that is required. We saw what annotations to use to enable each of the facets. We looked at how the client code had to change to invoke the secured service, and saw how the SOAP messages themselves changed to reflect the newly added security. In the tutorial we built a Web service that incorporated all three facets added to it in an incremental fashion.

Due to the "plain text" nature of SOAP messaging, it is important to have robust security capabilities when deploying Web services as a part of a production enterprise environment. WS-Security combined with WebLogic Server offers an excellent solution to this problem, allowing developers to easily deploy and maintain secure enterprise services.

References

  • Eclipse Documentation - documentation on using Eclipse
  • Ant - the official Web site for the Ant tool
  • OASIS Web Services Security - the home of the official Web services security spec
  • Gary Ng is a senior consultant with WebAge Solutions and has been involved in various J2EE projects since 2001.

    Matt Silver is a technology consultant and trainer, currently serving as a senior consultant for Web Age Solutions.