Learn with our tutorials and training

developerWorks provides tutorials, articles and other
technical resources to help you grow your development skills
on a wide variety of topics and products. Learn about a specific
product or take a course and get certified. So, what do you want to learn
about?

Featured products

Featured destinations

Find a community and connect

Learn from the experts and share with other developers in one of our
dev centers. Ask questions and get answers with dW answers. Search for local events
in your area. All in developerWorks communities.

This content is part # of # in the series: Message-level security with JAX-WS on WebSphere Application Server V7, Part 3

This content is part of the series:Message-level security with JAX-WS on WebSphere Application Server V7, Part 3

Stay tuned for additional content in this series.

In Part 1, you learned how to build JAX-WS web services that use
message-level security by using policy sets that give you a declarative
way of specifying how message-level security should be performed. That
method works well in most cases and is the preferred way to specify
message-level security. However, sometimes the consumers of the service
might need more dynamic control in order to programmatically change the
UsernameToken value or to dynamically specify which public key to use. The
WSS APIs give you this programmatic control over how the consumer builds a
SOAP message that adheres to the service provider's WS-Security policy
set. Additionally, the WSS APIs allow Spring clients to invoke JAX-WS
service providers on WebSphere Application Server V7 using
WS-Security.

Create a JAX-WS web
service

Let's start with a plain old Java object (POJO) annotated with a web
service annotation to define that POJO as a service provider. Simply
create a new Dynamic Web Project with a new Java class
and copy the code from Listing 1 into that class.

Figure 1. Service provider
dynamic web project

That's it! A simple POJO with the @WebService
annotation is all that is necessary to create a JAX-WS web service.

Secure the service
provider

In this article, we use WS-Security policy sets to require that SOAP
messages are encrypted and signed. Rational Application Developer V7.5
comes with a set of default policy sets; the examples in this article use
the Username WS-Security default policy set. To secure the server
provider, do the following:

Right-click the service provider and select Manage Policy Set
Attachment as shown in Figure 2.

Figure 2. Attach
policy set to service provider

In the End Point Definition dialog, shown in Figure
3, verify that HelloWorldProviderService is the
selected service and select <all endpoints> as
the list of endpoints that will attach to the policy set. Select
Username WSSecurity default and Provider
sample as the desired policy set and policy set binding.
Click OK, then Finish.

Figure 5. Verify
policy set and bindings

You've now configured the service provider to require WS-Security. The
Username WSSecurity default policy set uses the Username Token for
authentication, so you also need to enable security in the
administrative console. To do this, select Security =>
Global security and verify that both Enable
administrative security and Enable application
security are selected, as shown in Figure 6.

Tip: You need to restart WebSphere
Application Server if you had to enable security.

Figure 6. Enable
application security

Next we'll look at how to configure the client consumer to invoke this
service provider with WS-Security using the WSS APIs.

Generate a JAX-WS
consumer

Now that you have the service provider running on WebSphere Application
Server V7 with the WS-Security default policy set and sample bindings, you
can create a JAX-WS consumer that invokes this service provider by doing
the following:

From Rational Application Developer, create a new Java project with
the name HelloWorldConsumer.

Select the service provider from which Rational Application Developer
will generate a client proxy as shown in Figure 7.

Figure 7. Generate
JAX-WS client proxy

From the Web Service Client wizard, ensure that IBM WebSphere JAX-WS
is the chosen web service runtime then click the Client
project: link.

Select HelloWorldConsumer as the client
project.

Accept the defaults and click the Finish button,
which results in Rational Application Developer generating a JAX-WS
client proxy class and supporting classes.

Provide client credentials
programmatically

Now let's create a Java class that uses the generated JAX-WS proxy to
invoke the JAX-WS service provider. Because the service provider is
protected according to the specifications of the Username WS-Security
default policy set, you need to use the WSS APIs to build a SOAP message
programmatically that adheres to the service provider's policy set.

From the HelloWorldConsumer project, create a new Java
class called ClientTest and replace the
generated code with the code from Listing 2. For your convenience, a
project export of all the code in this article is included in the Download section.

The code sample in Listing 2 is configured to match the provider
sample binding that you attached to the service provider. If
you examine the binding's configuration in the WebSphere Application
Server administrative console, you'see settings for the keys used for
encryption, decryption, and signing. In a production setting, you should
customize the keys as demonstrated in Part 1 of this article series.

Test and verify

Now that you have secured the service provider and developed a service
consumer that uses the WSS APIs to adhere to the policy set requirements
of the service provider, you can verify that the code works.

From Rational Application Developer, right-click
ClientTest.java and select Run As =>
Run Configurations. You'll see the Run Configurations
dialog, as shown in Figure 8.

Figure 8. Set JAAS
arguments for ClientTest

The consumer needs to use Java Authentication and Authorization
Service (JAAS) to pass in the username credentials, so you need to
specify the following VM argument to point to the JAAS login
configuration file; for example, by default on the Windows platform:

If you examine the wsjaas_client.conf file, you'll see that it only
specifies how to find the classes used by JAAS and does not contain
any user credentials or WS-Security settings; that is all done
programmatically through the WSS APIs shown in Listing 2.

Now click Run to generate client results, as shown in
Figure 9, and server-side results, as shown in Figure 10.

Figure 11. SOAP
request and response seen through TCP/IP monitor

Add Spring to the mix

Many clients use the Spring framework to create web service clients, or
consumers. The Spring remoting capability provides that ability through a
configuration such as the one shown in Listing 3. Spring then essentially
creates a dynamic proxy on the fly by which it invokes a web service as
defined by the Web Service Definition Language (WSDL) in the
configuration. However, because this process is done dynamically at
runtime, the "attach policy set" to the client proxy capability
demonstrated in Part 1 doesn't have a client proxy to select in Rational
Application Developer that can attach to the policy set. Therefore, you
can use the WSS APIs to enable Spring clients to connect to a WebSphere
Application Server V7 web service protected by WS-Security policy
sets.

To do this, you can use JAX-WS handlers to intercept the dynamic Spring
proxy before it sends a SOAP request to the provider and modify the
request as required to comply with the service provider's policy set. As
shown in Listing 3, the Spring configuration contains a
handlerResolver property that specifies a
callback class. Also note in Listing 3 that the
serviceInterface used is the one generated by
Rational Application Developer V7.5.

Since only one handler is being used, Listing 4 shows the handler that uses
the WSS APIs to adhere to the Username WSSecurity default policy set
attached to the service provider. The code has comments to better explain
each part of the Java code. Note that this code is essentially the code in
Listing 2, but packaged in a SOAPHandler fashion.

The handler simply intercepts the outbound message and adds a UNT, then
signs and encrypts the various parts of the SOAP message as required by
the service provider. The keys used match the sample keys that were
attached to the service provider, but you can refer to Part 1 for information on how to customize the keys.

Once the handler is in place, you can create a Spring client that pulls in
the dynamic proxy that points to the web service provider deployed on
WebSphere Application Server V7. When this Spring bean is invoked, the
handler massages the outgoing message:

Summary

Message-level security is necessary for a variety of projects, and this
article series has taught you many facets of using WebSphere Application
Server V7 to support your message-level security needs. This third article
showed how to use the WSS APIs to take programmatic control over how the
client builds SOAP messages that comply with the security requirements of
a web service provider. That process allows you to dynamically change the
username/password pair, for example, in the SOAP header, or perhaps to
dynamically choose keys based on the user instance. Additionally, this
article showed how Spring clients can use the WSS APIs to consume web
services protected with message-level security.

Acknowledgment

The authors would like to give special thanks to Bill Dodd and Ching-Yun
Chao for their diligent review of this article and code.