Защита на уровне сообщений при помощи модели программирования JAX-WS на WebSphere Application Server V7: Часть 3. Программируемое управление клиентом при помощи программных интерфейсов Web Services Security

В части 1 вы узнали, как реализовать защиту на уровне сообщений при помощи JAX-WS на сервере WebSphere® Application Server V7. В части 2 (вы использовали маркер UsernameToken для программируемых решений JEE-авторизации. В части 3 вы узнаете, как с помощью программных интерфейсов Web Services Security (WSS) создать клиент JAX-WS, работающего с защищенным сервисом, выполняющимся на сервере WebSphere Application Server V7.

Хень-Вуй (Генри) Чун, старший архитектор Web-сервисов, IBM

Генри Чун (Henry Chung) - фотографияГенри Чун (Henry Chung) работает архитектором Web-сервисов в группе разработки WebSphere Web Services. До этого Генри был архитектором и ведущим разработчиком защиты Web-сервисов на платформе WebSphere. Более восьми лет он занимался разработкой программного обеспечения промежуточного уровня и создал большое количество функций защиты для платформы WebSphere. В настоящее время основное внимание он уделяет разработке новейших спецификаций WebSphere Web Services. Также он оказывает помощь клиентам и другим подразделениям IBM в применении Web-сервисов. Основной его целью является адаптация технологии WebSphere Web Services для решения практических задач.



Уильям Гриффит, архитектор связующего ПО для интеграции приложений, IBM

Билл Гриффит (Bill Griffith) - архитектор связующего ПО для интеграции приложений в IBM Software Group. Он разработал для клиентов десятки J2EE-приложений и приложений Lotus Domino. В настоящий момент он занимается разработкой сервис-ориентированных архитектур и даёт консультации по их внедрению и эксплуатации.



15.03.2012

В части 1 вы познакомились с созданием JAX-WS Web-сервисов, которые используют защиту на уровне сообщений с помощью наборов политик, дающих возможность указать декларативным способом, как должна выполняться защита. Это подход хорошо работает в большинстве случаев и является предпочтительным для задания защиты на уровне сообщений. Однако иногда может потребоваться динамическое управление потребителями сервиса в случае программного изменения значения UsernameToken или указания используемого открытого ключа. Интерфейсы WSS предоставляют возможность программно управлять процессом создания потребителем SOAP-сообщения, которое придерживается набора политик WS-Security поставщика сервиса. Кроме того, программные интерфейсы WSS позволяют Spring-клиентам вызывать поставщиков сервисов JAX-WS на сервере WebSphere Application Server V7 с использованием WS-Security.

Создание Web-сервиса JAX-WS

Начнем с простого Java-объекта в старом стиле (Plain Old Java Object - POJO) с аннотацией Web-сервиса, определяющей POJO-объект в качестве поставщика сервиса. Просто создайте новый динамический Web-проект с новым Java-классом и скопируйте в этот класс код из листинга 1.

Листинг 1. Код на стороне сервера
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;
  }
}

После сохранения кода отобразится экран, показанный на рисунке 1, с созданным классом HelloWorldProvider.

Рисунок 1. Динамический Web-проект поставщика сервиса
Рисунок 1. Динамический Web-проект поставщика сервиса

Вот и все! Простой POJO-объект с аннотацией @WebService - это все, что нужно для создания JAX-WS Web-сервиса.


Защита поставщика сервиса

В данной статье используются наборы политик WS-Security, требующие, чтобы SOAP-сообщения были зашифрованы и подписаны. Rational Application Developer V7.5 поставляется с комплектом наборов политик по умолчанию; в примерах данной статьи используется набор политик по умолчанию Username WS-Security. Для защиты поставщика сервиса сделайте следующее:

  1. Щелкните правой кнопкой мыши на поставщике сервиса и выберите Manage Policy Set Attachment, как показано на рисунке 2.
    Рисунок 2. Прикрепление набора политик к поставщику сервиса
    Рисунок 2. Прикрепление набора политик к поставщику сервиса
  2. В диалоговом окне End Point Definition, показанном на рисунке 3, выберите сервис HelloWorldProviderService, а затем <all endpoints> в качестве списка конечных точек, который будет прикреплен к набору политик. Выберите Username WSSecurity default и Provider sample в качестве требуемого набора политик и связывания набора политик. Нажмите OK, а затем Finish.
    Рисунок 3. Настройка набора политик Username WSSecurity default
    Рисунок 3. Настройка набора политик Username WSSecurity default
  3. Разверните проект на сервере WebSphere Application Server V7.
  4. Откройте консоль администратора вашей среды исполнения WebSphere Application Server V7, как показано на рисунке 4, и убедитесь, что набор политик и связывания были успешно прикреплены к поставщику сервиса.
    Рисунок 4. Запуск консоли администратора
    Рисунок 4. Запуск консоли администратора
  5. Выберите Services => Service providers => HelloWorldProviderService, как показано на рисунке 5. Обратите внимание, что набор политик Username WSSecurity default прикреплен вместе со связываниями Provider sample.
    Рисунок 5. Проверка набора политик и связываний
    Рисунок 5. Проверка набора политик и связываний
  6. Итак, вы настроили поставщика сервиса на использование WS-Security. Набор политик Username WSSecurity default использует для аутентификации Username Token, поэтому в консоли администратора необходимо включить защиту. Для этого выберите Security => Global security и убедитесь, что отмечены флажки Enable administrative security и Enable application security, как показано на рисунке 6.

    Совет. После включения защиты нужно перезапустить WebSphere Application Server.

    Рисунок 6. Включение защиты приложения
    Рисунок 6. Включение защиты приложения

    (Увеличенная версия рисунка 6)

Далее мы рассмотрим настройку потребителя для вызова поставщика сервиса с WS-Security при помощи программных интерфейсов WSS.


Создание потребителя сервиса JAX-WS

Теперь, когда у нас есть поставщик сервиса с набором политик WS-Security по умолчанию и эталонными связываниями, выполняющийся на сервере WebSphere Application Server V7, для вызова этого поставщика сервиса можно создать JAX-WS-потребителя, выполнив следующие действия:

  1. В Rational Application Developer создайте новый Java-проект под именем HelloWorldConsumer.
  2. Выберите поставщика сервиса, из которого Rational Application Developer будет генерировать прокси-клиента, как показано на рисунке 7.
    Рисунок 7. Создание прокси-клиента JAX-WS
    Рисунок 7. Создание прокси-клиента JAX-WS
  3. В мастере Web Service Client убедитесь, что в качестве среды исполнения Web-сервиса выбрана IBM WebSphere JAX-WS, и нажмите ссылку Client project:.
  4. Выберите HelloWorldConsumer в поле Client project name.
  5. Примите значения по умолчанию и нажмите кнопку Finish, в результате в Rational Application Developer будет создан класс прокси-клиента JAX-WS и поддерживающие классы.

Программное предоставление учетных данных клиента

Теперь создадим Java-класс, использующий сгенерированный JAX-WS-прокси для вызова поставщика сервиса JAX-WS. Поскольку поставщик сервиса защищен в соответствии со спецификациями набора политик Username WS-Security default, необходимо использовать интерфейсы WSS для создания программным способом SOAP-сообщения, которое придерживается набора политик поставщика сервиса.

В проекте HelloWorldConsumer создайте новый Java-класс ClientTest и замените сгенерированный код кодом из листинга 2. Для удобства читателей статьи весь код проекта включен в раздел Загрузка.

Листинг 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 прокси-клиент, сгенерированный из RAD
  HelloWorldProviderService srv = new HelloWorldProviderService();
  HelloWorldProvider port = srv.getHelloWorldProviderPort();
			
  // использовать BindingProvider для включения в контекст сообщения
  BindingProvider bp = (BindingProvider) port;
  Map<String,Object> requestContext = bp.getRequestContext();
		
  WSSFactory wssfactory = WSSFactory.getInstance();
  WSSGenerationContext generationContext = wssfactory.newWSSGenerationContext();
			
  // прикрепить маркер username к сообщению 
  UNTGenerateCallbackHandler untCallback = new 
    UNTGenerateCallbackHandler("admin", "admin",true,true);
  SecurityToken unt = wssfactory.newSecurityToken(UsernameToken.class,
    untCallback);
  generationContext.add(unt);
			
  // указать ключ для подписи в соответствии с конфигурацией 'образца поставщика', 
  // которая прикреплена к поставщику сервиса
  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);
			
  // указать, что подписывать
  signature.addSignPart(WSSSignature.BODY);
  signature.addSignPart(WSSSignature.ADDRESSING_HEADERS);
  signature.addSignPart(WSSSignature.TIMESTAMP);				
  signature.addSignPart(unt);
  generationContext.add(signature);
		
  // указать ключ для шифрования (ключ, ожидаемый поставщиком сервиса)
  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);
			
  // указать, что шифровать
  encryption.addEncryptPart(unt, false);
  encryption.addEncryptPart(WSSEncryption.BODY_CONTENT);
  encryption.addEncryptPart(WSSEncryption.SIGNATURE);
  generationContext.add(encryption);

  // дешифровать сообщение в соответствии с настройкой generationContext
  generationContext.process(requestContext);
			
  // указать ключ для дешифрования
  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);
				
  // использовать промежуточный центр сертификации для проверки сертификата
  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);
			
  // указать ключ проверки подписи
  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);
			
  // дешифровать сообщение в соответствии с настройкой consumerContext
  consumerContext.process(requestContext);
		
  String resp = port.sayHello("Griffith");
  System.out.println("[response] " + resp);
	
} catch(Exception e) {
  e.printStackTrace();
}
}
}

Не забудьте исправить значение KEY_PATH в соответствии с требованиями вашей системы.

Пример кода в листинге 2 настроен на соответствие эталонному связыванию поставщика, которое вы прикрепили к поставщику сервиса. Исследовав конфигурацию связывания в консоли администратора WebSphere Application Server, можно увидеть настройки ключей для шифрования, дешифрования и подписания. Для уровня производства необходимо настроить ключи в соответствии с частью 1 (EN) данной серии статей.


Тестирование и проверка

Теперь, когда у нас есть защищенный поставщик сервиса и разработанный потребитель сервиса, который использует программные интерфейсы WSS для соблюдения требований набора политик поставщика сервиса, можно проверить работу кода.

  1. В Rational Application Developer щелкните правой кнопкой мыши на ClientTest.java и выберите Run As => Run Configurations. Отобразится диалоговое окно Run Configurations, как показано на рисунке 8.
    Рисунок 8. Установка параметров JAAS для ClientTest
    Рисунок 8. Установка параметров JAAS для ClientTest
  2. Поскольку для передачи учетных данных Username потребитель должен использовать сервис Java Authentication and Authorization Service (JAAS), необходимо в поле VM arguments задать информацию, указывающую на конфигурационный файл входа в систему сервиса JAAS; например, по умолчанию на платформе Windows:
    -Djava.security.auth.login.config=”C:\Program 
    Files\IBM\SDP\runtimes\base_v7\profiles\was70profile1\properties
    \wsjaas_client.conf”

    Изучив файл wsjaas_client.conf, можно заметить, что он всего лишь указывает, как найти классы, и не содержит никаких пользовательских учетных данных или настроек WS-Security; все это генерируется программно посредством программных интерфейсов WSS, показанных в листинге 2.
  3. Нажмите Run, чтобы сгенерировать результаты на стороне клиента, как показано на рисунке 9, и на стороне сервера, как показано на рисунке 10.
    Рисунок 9. Результаты для JAX-WS потребителя
    Рисунок 9. Результаты для JAX-WS потребителя
    Рисунок 10. Результаты для JAX-WS поставщика
    Рисунок 10. Результаты для JAX-WS поставщика
  4. SOAP-сообщения запроса и ответа можно увидеть в мониторе TCP/IP Monitor, настройка которого описана в части 1 (см. рисунок 11).
    Рисунок 11. SOAP-запрос и SOAP-ответ в TCP/IP Monitor
    Рисунок 11. SOAP-запрос и SOAP-ответ в TCP/IP Monitor

    (Увеличенная версия рисунка 11)


Добавление Spring

Многие заказчики используют для создания клиентов Web-сервисов и потребителей инфраструктуру Spring. Spring предоставляет возможность удаленного взаимодействия посредством конфигурации, показанной в листинге 3. По существу, Spring на лету создает динамический прокси, при помощи которого вызывает Web-сервис, определенный в конфигурации на языке Web Service Definition Language (WSDL). Однако, поскольку этот процесс выполняется динамически во время исполнения, возможность "прикрепить набор политик" к прокси-клиенту, описанную в части 1 (EN), нельзя реализовать, т.к. в Rational Application Developer отсутствует прокси-клиент, к которому можно прикрепить набор политик. Зато можно использовать программные интерфейсы WSS, чтобы Spring-клиенты могли подключаться к защищенному при помощи наборов политик WS-Security Web-сервису на сервере WebSphere Application Server V7.

Для этого используются JAX-WS-обработчики, перехватывающие динамический Spring-прокси до отправки SOAP-запроса поставщику и модифицирующие запрос в соответствии с требованиями набора политик поставщика сервиса. Как показано в листинге 3, конфигурация Spring содержит свойство (property) handlerResolver, указывающее класс обратного вызова. Обратите внимание, что в листинге 3 используется свойство serviceInterface, которое сгенерировал Rational Application Developer V7.5.

Листинг 3. Конфигурация Spring (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>

Пользовательский обработчик просто предоставляет список обработчиков для вызова, как показано в листинге 4.

Листинг 4. Список пользовательского обработчика на стороне клиента
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;
  }
}

Поскольку используется только один обработчик, в листинге 4 показан обработчик, который использует программные интерфейсы WSS, позволяющие придерживаться набора политик по умолчанию Username WSSecurity, прикрепленного к поставщику сервиса. Java-код содержит комментарии, объясняющие отдельные его части. Обратите внимание, что это практически тот же код, что и в листинге 2, но упакованный в форме SOAPHandler.

Листинг 5. Java-класс CredsHandler
package com.ibm.dwexample.client; 
public class CredsHandler implements SOAPHandler<SOAPMessageContext> {
// TODO: должен указывать на ключи на вашей машине
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);
  // касается только исходящего сообщения
if (outbound) {
  System.out.println("[CredsHandler] " + messagecontext);
 try {
  WSSFactory wssfactory = WSSFactory.getInstance();
  WSSGenerationContext generationContext = wssfactory.newWSSGenerationContext();
  // прикрепить маркер username к сообщению
  UNTGenerateCallbackHandler untCallback = new UNTGenerateCallbackHandler("admin", 
    "admin",true,true);
  SecurityToken unt = wssfactory.newSecurityToken(UsernameToken.class, untCallback);
  generationContext.add(unt);
  // указать ключ для подписи в соответствии с конфигурацией 'образца поставщика',
  // которая прикреплена к поставщику сервиса 
  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);
  // указать, что подписывать
  signature.addSignPart(WSSSignature.BODY);
  signature.addSignPart(WSSSignature.ADDRESSING_HEADERS);
  signature.addSignPart(WSSSignature.TIMESTAMP);
  signature.addSignPart(unt);
  generationContext.add(signature);
  // указать ключ для шифрования (ключ, ожидаемый поставщиком сервиса)
  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);
  // указать, что шифровать
  encryption.addEncryptPart(unt, false);
  encryption.addEncryptPart(WSSEncryption.BODY_CONTENT);
  encryption.addEncryptPart(WSSEncryption.SIGNATURE);
  generationContext.add(encryption);
  // дешифровать сообщение в соответствии с настройкой generationContext
  generationContext.process(messagecontext);
  // указать ключ для дешифрования
  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);
  // использовать промежуточный центр сертификации для проверки сертификата
  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);
  // указать ключ проверки подписи
  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);
  // дешифровать сообщение в соответствии с настройкой consumerContext
  consumerContext.process(messagecontext);
} catch (Exception e) {
  e.printStackTrace();
}
}
return true;
}}

Обработчик просто перехватывает исходящее сообщение и добавляет UNT, затем подписывает и шифрует различные части SOAP-сообщения в соответствии с требованиями поставщика сервиса. Используемые ключи соответствуют образцам ключей, прикрепленным к поставщику сервиса (информацию о настройке ключей можно получить в части 1 ).

После размещения обработчика может быть создан Spring-клиент, который использует динамический прокси, указывающий на поставщика Web-сервиса, развернутого на WebSphere Application Server V7. Когда вызывается bean-компонент Spring, обработчик изменяет исходящее сообщение:

Листинг 6. 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();
    }
  }
}

Примечание. Клиенту SpringTest также необходима JAAS-конфигурация, показанная на рисунке 8.


Заключение

Защита на уровне сообщений необходима в различных проектах, и в данной серии статей затронуты многие аспекты использования WebSphere Application Server V7 для обеспечения защиты на уровне сообщений. В настоящей статье показано, как использовать интерфейсы WSS для программного управления процессом создания потребителем SOAP-сообщения, которое соответствует требованиям безопасности поставщика Web-сервиса. Этот процесс позволяет динамически изменять пару имя пользователя/пароль (например, в SOAP-заголовке) или динамически выбирать ключи, основанные на экземпляре пользователя. Кроме того, статья демонстрирует, как Spring-клиенты могут использовать программные интерфейсы WSS для работы с защищенными на уровне сообщений Web-сервисами.


Благодарность

Авторы благодарят Билла Додда и Чин-Юнь Чао за внимательное прочтение данной статьи и проверку кода.


Загрузка

ОписаниеИмяРазмер
Пример кода проектаjaxws_wssapi.zip2.5 МБ

Ресурсы

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=WebSphere, SOA и web-сервисы
ArticleID=802105
ArticleTitle=Защита на уровне сообщений при помощи модели программирования JAX-WS на WebSphere Application Server V7: Часть 3. Программируемое управление клиентом при помощи программных интерфейсов Web Services Security
publish-date=03152012