Skip to main content

By clicking Submit, you agree to the developerWorks terms of use.

The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

All information submitted is secure.

  • Close [x]

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerworks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

By clicking Submit, you agree to the developerWorks terms of use.

All information submitted is secure.

  • Close [x]

Message-level security with JAX-WS on WebSphere Application Server V7, Part 3: Programmatic client control using Web Services Security APIs

Hyen-Vui (Henry) Chung, Senior Web Services Architect, IBM
Henry Chung photo
Henry Chung is an architect on the WebSphere Web Services development team. Prior to this role, Henry was the architect and lead developer of Web services security on the WebSphere platform. Henry has been in middleware development for over eight years and has developed many security features for the WebSphere platform. His current focus is leading the development of the latest WebSphere Web services specifications. He also helps customers and other IBM teams apply Web services solutions. His primary goal is to deliver WebSphere Web services technology to meet real-world needs.
Bill Griffith (wgriffith@us.ibm.com), Senior IT Architect, IBM
Bill Griffith photo
Bill Griffith is a Senior IT Architect in the Worldwide WebSphere Business Partner organization. In this role, Bill works with IBM business partners to architect and design business partner solutions that leverage IBM middleware as a way to decrease time-to-market and decrease costs.

Summary:  In Part 1, you learned how to provide message-level security using JAX-WS on WebSphere® Application Server V7. In Part 2, you used the UsernameToken for JEE programmatic authorization decisions. In Part 3, you'll learn how to develop a JAX-WS client that can consume a secure service running on WebSphere Application Server V7 using the Web Services Security (WSS) APIs.

View more content in this series

Date:  31 Aug 2010
Level:  Intermediate PDF:  A4 and Letter (484KB | 17 pages)Get Adobe® Reader®
Also available in:   Russian

Activity:  10602 views
Comments:  

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.


Listing 1. Server-side code

package com.ibm.dwexample;
import javax.jws.WebService;

@WebService
public class HelloWorldProvider {
  public String sayHello(String msg) {
    System.out.println("[helloworld service] received " + msg);
    return "Hello " + msg;
  }
}

After you have saved the code, you should see something like Figure 1 with the HelloWorldProvider class created.


Figure 1. Service provider dynamic web project
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:

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

    Figure 2. Attach policy set to service provider
    Attach policy                     set to service provider

  2. 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 3. Set Username WSSecurity default policy set
    Set Username                     WSSecurity default policy set

  3. Deploy the project to WebSphere Application Server V7.
  4. Verify that the policy set and bindings were successfully attached to the service provider by opening the administrative console of your WebSphere Application Server V7 runtime, as shown in Figure 4.

    Figure 4. Run administrative console
    Run                     administrative console

  5. Select Services => Service providers => HelloWorldProviderService, as shown in Figure 5. Notice that the Username WSSecurity default policy set is attached along with the Provider sample bindings.

    Figure 5. Verify policy set and bindings
    Verify policy                     set and bindings

  6. 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
    In the adminstrative console, navigate to Security and then Global security to verify that both Enable administrative security and Enable application security are selected.

    (See a larger version of Figure 6.)

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:

  1. From Rational Application Developer, create a new Java project with the name HelloWorldConsumer.
  2. 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
    Generate                             JAX-WS client proxy

  3. From the Web Service Client wizard, ensure that IBM WebSphere JAX-WS is the chosen web service runtime then click the Client project: link.
  4. Select HelloWorldConsumer as the client project.
  5. 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.


Listing 2. ClientTest.java

package com.ibm.dwexample.client;

import java.io.FileInputStream;
import java.security.cert.CertStore;
import java.security.cert.CertificateFactory;
import java.security.cert.CollectionCertStoreParameters;
import java.security.cert.X509Certificate;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import javax.xml.ws.BindingProvider;
import com.ibm.dwexample.HelloWorldProvider;
import com.ibm.dwexample.HelloWorldProviderService;
import com.ibm.websphere.wssecurity.callbackhandler.UNTGenerateCallbackHandler;
import com.ibm.websphere.wssecurity.callbackhandler.X509ConsumeCallbackHandler;
import com.ibm.websphere.wssecurity.callbackhandler.X509GenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.WSSConsumingContext;
import com.ibm.websphere.wssecurity.wssapi.WSSFactory;
import com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext;
import com.ibm.websphere.wssecurity.wssapi.decryption.WSSDecryption;
import com.ibm.websphere.wssecurity.wssapi.encryption.WSSEncryption;
import com.ibm.websphere.wssecurity.wssapi.signature.WSSSignature;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
import com.ibm.websphere.wssecurity.wssapi.token.UsernameToken;
import com.ibm.websphere.wssecurity.wssapi.token.X509Token;
import com.ibm.websphere.wssecurity.wssapi.verification.WSSVerification;

public class ClientTest {

public static void main(String[] args) {

final String KEY_PATH = "C:/Program Files/IBM/SDP/runtimes/base_v7/profiles
  /was70profile2/etc/ws-security/samples/";
		
try {
  // JAX-WS proxy client generated from RAD
  HelloWorldProviderService srv = new HelloWorldProviderService();
  HelloWorldProvider port = srv.getHelloWorldProviderPort();
			
  // use BindingProvider to hook into message context
  BindingProvider bp = (BindingProvider) port;
  Map<String,Object> requestContext = bp.getRequestContext();
		
  WSSFactory wssfactory = WSSFactory.getInstance();
  WSSGenerationContext generationContext = wssfactory.newWSSGenerationContext();
			
  // Attach the username token to the message 
  UNTGenerateCallbackHandler untCallback = new 
    UNTGenerateCallbackHandler("admin", "admin",true,true);
  SecurityToken unt = wssfactory.newSecurityToken(UsernameToken.class,
    untCallback);
  generationContext.add(unt);
			
  // specify key for signing to match the configuration of the ‘provider sample’ 
  // that is attached to service provider
  X509GenerateCallbackHandler signerCallback = new
    X509GenerateCallbackHandler("", 
    KEY_PATH + "dsig-sender.ks", 
    "jks", "client".toCharArray(),"soaprequester", "client".toCharArray(),
    "CN=SOAPRequester, OU=TRL, O=IBM, ST=Kanagawa, C=JP", null);
  SecurityToken signerToken=wssfactory.newSecurityToken(X509Token.class,
    signerCallback);
  WSSSignature signature = wssfactory.newWSSSignature(signerToken);
			
  // specify what to sign
  signature.addSignPart(WSSSignature.BODY);
  signature.addSignPart(WSSSignature.ADDRESSING_HEADERS);
  signature.addSignPart(WSSSignature.TIMESTAMP);				
  signature.addSignPart(unt);
  generationContext.add(signature);
		
  // specify key to use for encryption (same key service provider expecting)
  X509GenerateCallbackHandler encryptionCallback = new
    X509GenerateCallbackHandler("",
    KEY_PATH + "enc-sender.jceks", 
    "jceks", "storepass".toCharArray(),"bob", null, "CN=Bob, O=IBM, C=US",null);
  SecurityToken encryptingToken = wssfactory.newSecurityToken(X509Token.class, 
    encryptionCallback);
  WSSEncryption encryption = wssfactory.newWSSEncryption(encryptingToken);
  encryption.setKeyEncryptionMethod(WSSEncryption.KW_RSA15);
			
  // specify what to encrypt
  encryption.addEncryptPart(unt, false);
  encryption.addEncryptPart(WSSEncryption.BODY_CONTENT);
  encryption.addEncryptPart(WSSEncryption.SIGNATURE);
  generationContext.add(encryption);

  // encode message according to generationContext setting
  generationContext.process(requestContext);
			
  // specify key to be used for decryption
  WSSConsumingContext consumerContext = wssfactory.newWSSConsumingContext();
  X509ConsumeCallbackHandler decryptionCallback = new
    X509ConsumeCallbackHandler(
    "", KEY_PATH + "enc-receiver.jceks", "jceks", "storepass".toCharArray(),
    "bob", "keypass".toCharArray(), "CN=Bob, O=IBM, C=US");
  WSSDecryption decryption = wssfactory.newWSSDecryption(X509Token.class, 
    decryptionCallback);
  decryption.addAllowedKeyEncryptionMethod(WSSEncryption.KW_RSA15);
  decryption.addRequiredDecryptPart(WSSDecryption.BODY_CONTENT);
  decryption.addRequiredDecryptPart(WSSDecryption.SIGNATURE);
  consumerContext.add(decryption);
				
  // Use intermediate certificate authority to verify certificate
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  X509Certificate cacert = (X509Certificate) cf.generateCertificate(new 
    FileInputStream(KEY_PATH + "intca2.cer"));
  Set<Object> eeCerts = new HashSet<Object>();
  eeCerts.add(cacert);
  java.util.List<CertStore> certList = new
    java.util.ArrayList<CertStore>();
  CollectionCertStoreParameters certparam = new
    CollectionCertStoreParameters(eeCerts);
  CertStore cert = CertStore.getInstance("Collection", certparam,
    "IBMCertPath");
  certList.add(cert);
			
  // specify signature verification key
  X509ConsumeCallbackHandler verificationHandler = new
    X509ConsumeCallbackHandler(
    KEY_PATH + "dsig-receiver.ks", "jks", "server".toCharArray(),
    certList, java.security.Security.getProvider("IBMCertPath"));
  WSSVerification verification = 
    wssfactory.newWSSVerification(X509Token.class,verificationHandler);
  consumerContext.add(verification);
			
  // decode message according to consumerContext settings
  consumerContext.process(requestContext);
		
  String resp = port.sayHello("Griffith");
  System.out.println("[response] " + resp);
	
} catch(Exception e) {
  e.printStackTrace();
}
}
}

Be sure to correct the KEY_PATH value as required on your system.

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.

  1. 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
    Set JAAS                             arguments for ClientTest

  2. 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:
    -Djava.security.auth.login.config=”C:\Program 
    Files\IBM\SDP\runtimes\base_v7\profiles\was70profile1\properties
    \wsjaas_client.conf”
    

    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.
  3. Now click Run to generate client results, as shown in Figure 9, and server-side results, as shown in Figure 10.

    Figure 9. JAX-WS consumer results
    JAX-WS consumer results..



    Figure 10. JAX-WS provider results
    JAX-WS provider results.

  4. You can also use the TCP/IP monitor (see Part 1 for how to configure) to see the SOAP request and response messages, as shown in Figure 11.

    Figure 11. SOAP request and response seen through TCP/IP monitor
    Use the TCP/IP monitor to see the SOAP request and response messages.

    (See a larger version of Figure 11.)


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.


Listing 3. Spring configuration (config/clientSpring.xml)

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns=http://www.springframework.org/schema/beans
  xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
  xsi:schemaLocation="http://www.springframework.org/schema/beans   
  http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">

<bean id="myHandler" class="com.ibm.dwexample.client.MyHandlerResolver"/>
<bean id="helloProxy"   
      class="org.springframework.remoting.jaxws.JaxWsPortProxyFactoryBean">
  <property name="serviceInterface" 
            value="com.ibm.dwexample.HelloWorldProvider"/>
  <property name="wsdlDocumentUrl" 
      value="http://localhost:9080/HelloWorldProject/HelloWorldProviderService?WSDL" />
  <property name="namespaceUri" value="http://dwexample.ibm.com/" />
  <property name="serviceName" value="HelloWorldProviderService" />
  <property name="portName" value="HelloWorldProviderPort" />
  <property name="handlerResolver" ref="myHandler"/>
</bean>
</beans>

The custom handler simply provides a list of handlers to invoke as shown in Listing 4.


Listing 4. Client-side custom handler list

package com.ibm.dwexample.client;
public class MyHandlerResolver implements HandlerResolver {

  public java.util.List<Handler> getHandlerChain(PortInfo portInfo) {
    List<Handler> handlerChain = new ArrayList<Handler>();
    CredsHandler credsHandler = new CredsHandler();
    handlerChain.add(credsHandler);
    return handlerChain;
  }
}

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.


Listing 5. CredsHandler Java class

package com.ibm.dwexample.client; 
public class CredsHandler implements SOAPHandler<SOAPMessageContext> {
// TODO:  must point to keys on your system
final String KEY_PATH = "C:/Program 
Files/IBM/SDP/runtimes/base_v7/profiles/was70profile2/etc/ws-security/samples/";

public void close(MessageContext messagecontext) {}
public Set<QName> getHeaders() {return null;}
public boolean handleFault(SOAPMessageContext messagecontext){return true;}
public boolean handleMessage(SOAPMessageContext messagecontext) {
  Boolean outbound = (Boolean)  
    messagecontext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
  // only concerned with outbound
if (outbound) {
  System.out.println("[CredsHandler] " + messagecontext);
 try {
  WSSFactory wssfactory = WSSFactory.getInstance();
  WSSGenerationContext generationContext = wssfactory.newWSSGenerationContext();
  // Attach the username token to the message 
  UNTGenerateCallbackHandler untCallback = new UNTGenerateCallbackHandler("admin", 
    "admin",true,true);
  SecurityToken unt = wssfactory.newSecurityToken(UsernameToken.class, untCallback);
  generationContext.add(unt);
  // specify key for signing to match the configuration of the 'provider sample'
  // that is attached to the service provider  
  X509GenerateCallbackHandler signerCallback = new X509GenerateCallbackHandler("", 
    KEY_PATH + "dsig-sender.ks", 
    "jks", "client".toCharArray(),"soaprequester", "client".toCharArray(),
    "CN=SOAPRequester, OU=TRL, O=IBM, ST=Kanagawa, C=JP", null);
  SecurityToken signerToken = wssfactory.newSecurityToken(X509Token.class, 
    signerCallback);
  WSSSignature signature = wssfactory.newWSSSignature(signerToken);
  // specify what to sign
  signature.addSignPart(WSSSignature.BODY);
  signature.addSignPart(WSSSignature.ADDRESSING_HEADERS);
  signature.addSignPart(WSSSignature.TIMESTAMP);
  signature.addSignPart(unt);
  generationContext.add(signature);
  // specify key to use for encryption (same key service provider expecting)
  X509GenerateCallbackHandler encryptionCallback = new 
    X509GenerateCallbackHandler("",
    KEY_PATH + "enc-sender.jceks", 
    "jceks", "storepass".toCharArray(),"bob", null, "CN=Bob, O=IBM, C=US",null);
  SecurityToken encryptingToken = wssfactory.newSecurityToken(X509Token.class, 
   encryptionCallback);
  WSSEncryption encryption = wssfactory.newWSSEncryption(encryptingToken);
  encryption.setKeyEncryptionMethod(WSSEncryption.KW_RSA15);
  // specify what to encrypt
  encryption.addEncryptPart(unt, false);
  encryption.addEncryptPart(WSSEncryption.BODY_CONTENT);
  encryption.addEncryptPart(WSSEncryption.SIGNATURE);
  generationContext.add(encryption);
  // encode message according to generationContext settings
  generationContext.process(messagecontext);
  // specify key to be used for decryption
  WSSConsumingContext consumerContext = wssfactory.newWSSConsumingContext();
  X509ConsumeCallbackHandler decryptionCallback = new X509ConsumeCallbackHandler(
    "", KEY_PATH + "enc-receiver.jceks", "jceks", "storepass".toCharArray(),
    "bob", "keypass".toCharArray(), "CN=Bob, O=IBM, C=US");
  WSSDecryption decryption = wssfactory.newWSSDecryption(X509Token.class, 
    decryptionCallback);
  decryption.addAllowedKeyEncryptionMethod(WSSEncryption.KW_RSA15);
  decryption.addRequiredDecryptPart(WSSDecryption.BODY_CONTENT);
  decryption.addRequiredDecryptPart(WSSDecryption.SIGNATURE);
  consumerContext.add(decryption);
  // use intermediate certificate authority to verify certificate
  CertificateFactory cf = CertificateFactory.getInstance("X.509");
  X509Certificate cacert = (X509Certificate) cf.generateCertificate(new 
    FileInputStream(KEY_PATH + "intca2.cer"));
  Set<Object> eeCerts = new HashSet<Object>();
  eeCerts.add(cacert);
  java.util.List<CertStore> certList = new java.util.ArrayList<CertStore>();
  CollectionCertStoreParameters certparam = new 
    CollectionCertStoreParameters(eeCerts);
  CertStore cert = CertStore.getInstance("Collection", certparam, "IBMCertPath");
  certList.add(cert);
  // specify signature verification key
  X509ConsumeCallbackHandler verificationHandler = new X509ConsumeCallbackHandler(
    KEY_PATH + "dsig-receiver.ks", "jks", "server".toCharArray(),
    certList, java.security.Security.getProvider("IBMCertPath"));
  WSSVerification verification = 
    wssfactory.newWSSVerification(X509Token.class,verificationHandler);
  consumerContext.add(verification);
  // decode message according to consumerContext settings
  consumerContext.process(messagecontext);
} catch (Exception e) {
  e.printStackTrace();
}
}
return true;
}}


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:


Listing 6. Client-side SpringTest

package com.ibm.example.client;
import com.ibm.example.proxy.HelloWorld;
import com.ibm.example.proxy.HelloWorldService;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class SpringTest {

  public static void main(String[] args) {
		
    try {
      ApplicationContext springCTX = new 
      ClassPathXmlApplicationContext("config/clientSpring.xml");
      HelloWorldProvider port = (HelloWorldProvider) springCTX.getBean("helloProxy");
      String resp = port.sayHello("Griffith");
      System.out.println("[response] " + resp);
    } catch(Exception e) {
      e.printStackTrace();
    }
  }
}

Note: The SpringTest client also needs the JAAS configuration shown Figure 8.


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.



Download

DescriptionNameSizeDownload method
Sample project codejaxws_wssapi.zip2.5MBHTTP

Information about download methods


Resources

About the authors

Henry Chung photo

Henry Chung is an architect on the WebSphere Web Services development team. Prior to this role, Henry was the architect and lead developer of Web services security on the WebSphere platform. Henry has been in middleware development for over eight years and has developed many security features for the WebSphere platform. His current focus is leading the development of the latest WebSphere Web services specifications. He also helps customers and other IBM teams apply Web services solutions. His primary goal is to deliver WebSphere Web services technology to meet real-world needs.

Bill Griffith photo

Bill Griffith is a Senior IT Architect in the Worldwide WebSphere Business Partner organization. In this role, Bill works with IBM business partners to architect and design business partner solutions that leverage IBM middleware as a way to decrease time-to-market and decrease costs.

Report abuse help

Report abuse

Thank you. This entry has been flagged for moderator attention.


Report abuse help

Report abuse

Report abuse submission failed. Please try again later.


developerWorks: Sign in


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Select information in your developerWorks profile is displayed to the public, but you may edit the information at any time. Your first name, last name (unless you choose to hide them), and display name will accompany the content that you post.

Choose your display name

The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


Rate this article

Comments

Help: Update or add to My dW interests

What's this?

This little timesaver lets you update your My developerWorks profile with just one click! The general subject of this content (AIX and UNIX, Information Management, Lotus, Rational, Tivoli, WebSphere, Java, Linux, Open source, SOA and Web services, Web development, or XML) will be added to the interests section of your profile, if it's not there already. You only need to be logged in to My developerWorks.

And what's the point of adding your interests to your profile? That's how you find other users with the same interests as yours, and see what they're reading and contributing to the community. Your interests also help us recommend relevant developerWorks content to you.

View your My developerWorks profile

Return from help

Help: Remove from My dW interests

What's this?

Removing this interest does not alter your profile, but rather removes this piece of content from a list of all content for which you've indicated interest. In a future enhancement to My developerWorks, you'll be able to see a record of that content.

View your My developerWorks profile

Return from help

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, SOA and Web services
ArticleID=548271
ArticleTitle=Message-level security with JAX-WS on WebSphere Application Server V7, Part 3: Programmatic client control using Web Services Security APIs
publish-date=08312010
author1-email=hychung@us.ibm.com
author1-email-cc=crothemi@us.ibm.com
author2-email=wgriffith@us.ibm.com
author2-email-cc=crothemi@us.ibm.com

Tags

Help
Use the search field to find all types of content in My developerWorks with that tag.

Use the slider bar to see more or fewer tags.

For articles in technology zones (such as Java technology, Linux, Open source, XML), Popular tags shows the top tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), Popular tags shows the top tags for just that product zone.

For articles in technology zones (such as Java technology, Linux, Open source, XML), My tags shows your tags for all technology zones. For articles in product zones (such as Info Mgmt, Rational, WebSphere), My tags shows your tags for just that product zone.

Use the search field to find all types of content in My developerWorks with that tag. Popular tags shows the top tags for this particular content zone (for example, Java technology, Linux, WebSphere). My tags shows your tags for this particular content zone (for example, Java technology, Linux, WebSphere).

Try IBM PureSystems. No charge.

Special offers