Web-сервисы Java: Детальное использование WS-Security

Применение WS-Security на уровне операций или сообщений

WS-Security для Web-сервисов SOAP не обязательно применять целиком. Выбирая конфигурацию WS-Security на уровне сообщений или операций, можно применять нужную степень защиты для каждого случая обмена данными, сокращая или исключая накладные расходы в тех операциях, которые не нуждаются в полноценной защите. Денис Сосновский продолжает свой цикл статей о Web-сервисах Java, рассматривая детальную настройку WS-Security средствами языка описания Web-сервисов(WSDL) с использованием Apache Axis2 и Rampart.

Денис Сосноски, консультант, Sosnoski Software Solutions, Inc.

Денис Сосноски (Dennis Sosnoski) - основатель и ведущий специалист консалтинговой компании по технологиям Java - Sosnoski Software Solutions, Inc., специализирующейся в обучении и консультировании по проблемам XML и Web-сервисов. Он имеет более чем 30-летний опыт работы в профессиональном проектировании ПО, специализируясь на серверных XML и Java-технологиях. Денис является основным разработчиком интегрированной системы с открытым программным кодом JiBX XML Data Binding, построенной на базе технологии классов Java и связанной системы Web-сервисов JibxSoap, также как и системы Web-сервисов Apache Axis2. Он также был одним их экспертов при разработке спецификаций JAX-WS 2.0.



26.12.2011

В простой среде Web-сервисов клиенты подключаются непосредственно к серверам, а серверы выполняют всю необходимую обработку запроса. Как следует из прошлой статьи этого цикла, в подобной среде SSL-соединение способно обеспечить превосходную защиту для большинства целей. Но в более сложных средах, которые встречаются все чаще, в обработке запроса участвуют несколько уровней серверов. На этом подходе основывается идея согласования сервисов, все более популярная во многих корпоративных средах, как и идея сервис-ориентированной архитектуры (SOA). В средах такого типа необходима более мощная альтернатива WS-Security.

Об этом цикле статей

Web-сервисы ― важная функция технологии Java™ в корпоративных вычислениях. В этом цикле статей консультант по XML и Web-сервисам Денис Сосновский рассказывает об основных структурах и технологиях, важных для Java-разработчиков, использующих Web-сервисы. Следите за статьями цикла, чтобы быть в курсе последних разработок в данной области и знать, как применить их в своих собственных проектах.

Как говорилось в предыдущей статье, WS-Security расходует много ресурсов. Один из способов сокращения этих расходов ― установить WS-SecurityPolicy для каждой отдельной операции или даже сообщения, определенного сервисом, вместо того, чтобы применять единую политику к сервису целиком. Детальный подход к использованию WS-Security требует больше внимания, чем универсальный, но его правильное применением может снизить накладные расходы для наиболее часто используемых операций без ослабления степени их защиты.

Определение политики

Пример приложения, используемый для этой статьи, тот же, что и в статьях Основы стандарта Axis2 WS-Security и Подпись и шифрование с помощью Axis2 WS-Security – простая служба управления библиотекой. (Полный исходный код примера для этой статьи приведен в разделе Загрузки.) В этом сервисе определены три операции:

  • getBook - получение сведений о конкретной книге, найденной по стандартному международному номеру книги (ISBN);
  • getBooksByType - получение сведений обо всех книгах определенного типа;
  • addBook - добавление новой книги в библиотеку.

Чтобы внести некоторое разнообразие в использование средств безопасности, в этой статье предполагается, что:

  • операция getBook может свободно предоставляться любому никому (защита отсутствует);
  • операция getBooksByType требует авторизации (то есть требуется UsernameToken;
  • операция addBook регистрирует, кто какую книгу добавил (с помощью подписи сообщений-запросов).

В предыдущих статьях мы показали, как настроить Axis2/Rampart, добавив документ WS-SecurityPolicy к экземпляру org.apache.axis2.client.ServiceClient (на стороне клиента) или путем внедрения политики в конфигурацию службы services.xml (на стороне сервера). Этот подход работает и может быть полезным при тестировании, но для промышленного использования WS-SecurityPolicy лучше всего связать непосредственно с определением сервиса, встроенного в документ WSDL. WS-Policy и WS-SecurityPolicy предназначены для поддержки такого вложения с помощью ссылок из определений <wsdl:binding>, <wsdl:binding>/<wsdl:operation> или <wsdl:binding>/<wsdl:operation>/<wsdl:message>, используемых для определения соответствующей политики в применении к такой связи, операции или сообщению. Axis2 1.4.1 осуществляет предварительную обработку политик, встроенных в WSDL, и в текущей версии программы Axis2 1.5 реализация этой обработки улучшилась. Для демонстрации использования политики в WSDL в этой статье используется код версии Axis2 1.5 в сочетании с пока не выпущенным черновым кодом Rampart (который должен со временем выйти как Rampart 1.5).

В листинге 1 показан код WSDL для примера приложения с добавленной политикой и ссылками из соответствующих мест. (Листинг 1 отредактирован с учетом длины и ширины страницы; полный код WSDL находится в файле library.wsdl загрузки). Каждая политика определяет значение Id, на которое затем ссылаются соответствующие операции (в случае политики UsernameToken) или сообщения (в случае политики подписи), как показано жирным шрифтом.

Листинг 1. WSDL с детальными политиками безопасности
<wsdl:definitions targetNamespace="http://ws.sosnoski.com/library/wsdl"
    xmlns:wns="http://ws.sosnoski.com/library/wsdl"
    xmlns:tns="http://ws.sosnoski.com/library/types"
    xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
    xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/">

  <!-- Политика для подписания сообщения с включением сертификата клиента в 
  каждое сообщение серверу-->
  <wsp:Policy wsu:Id="SignOnly" 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:AsymmetricBinding
            xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
          <wsp:Policy>
            <sp:InitiatorToken>
              <wsp:Policy>
                <sp:X509Token sp:IncludeToken=".../IncludeToken/AlwaysToRecipient"/>
              </wsp:Policy>
            </sp:InitiatorToken>
            ...
          </wsp:Policy>
        </sp:AsymmetricBinding>
        <sp:SignedParts
            xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702">
          <sp:Body/>
        </sp:SignedParts>

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

  <!-- Policy for UsernameToken with plaintext password, sent from client to
    server only -->
  <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=".../IncludeToken/AlwaysToRecipient"/>
          </wsp:Policy>
        </sp:SupportingTokens>
      </wsp:All>
    </wsp:ExactlyOne>
  </wsp:Policy>
  ...
  <wsdl:binding name="LibrarySoapBinding" type="wns:Library">

    <wsdlsoap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http"/>
    <wsdl:operation name="getBook">
      <wsdlsoap:operation soapAction="urn:getBook"/>
      <wsdl:input name="getBookRequest">
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getBookResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="getBooksByType">
      <wsp:PolicyReference
          xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
          URI="#UsernameToken"/>
      <wsdlsoap:operation soapAction="urn:getBooksByType"/>
      <wsdl:input name="getBooksByTypeRequest">
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="getBooksByTypeResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

    <wsdl:operation name="addBook">
      <wsdlsoap:operation soapAction="urn:addBook"/>
      <wsdl:input name="addBookRequest">
        <wsp:PolicyReference
            xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
            URI="#SignOnly"/>
        <wsdlsoap:body use="literal"/>
      </wsdl:input>
      <wsdl:output name="addBookResponse">
        <wsdlsoap:body use="literal"/>
      </wsdl:output>
    </wsdl:operation>

  </wsdl:binding>
  <wsdl:service name="library-granular">
    ...
  </wsdl:service>
</wsdl:definitions>

В листинге 1 все политики и код WSDL взяты из предыдущих статей, хотя там они не были объединены таким образом. Однако в этих политиках можно заметить одну существенную особенность: все предыдущие версии содержали сведения о конфигурации Rampart, которая была конфигурацией для клиента или для сервера. Теперь, когда политика встроена в WSDL, нецелесообразно включать Rampart непосредственно в конфигурацию. (Вам нужно отредактировать код WSDL, используя данные своей конфигурации клиента Rampart, и восстанавливать его всякий раз при ее изменении, а на сервере ваша конфигурация Rampart будет открыта для каждого, кто имеет доступ к WSDL). Поэтому в примере кода информация о конфигурации настраивается отдельно. Для этого используются вариации того же метода, который уже применялся для политик с включенной конфигурацией Rampart.


Со стороны клиента

С точки зрения пользователя генерация кода из WSDL работает одинаково, независимо от того, включена ли WS-политика, или нет. Если заглянуть внутрь клиентской заглушки, сгенерированной из кода WSDL, содержащего WS-Policy, можно увидеть, что политика подключается непосредственно к компонентам описания сервиса при его построении, но это скрыто внутри реализации и не влияет на методы интерфейса, которые использует клиентский код.

Чтобы использовать конфигурацию WS-SecurityPolicy для клиента, необходимо выполнить некоторые действия в коде клиента. Как минимум, нужно задействовать модуль Rampart в org.apache.axis2.client.ServiceClient, связанный с экземпляром заглушки. Этот шаг необходим даже при включении сведений о конфигурации Rampart в WSDL. К сожалению, в текущей версии не просматривается никакого рационального способа включить Rampart на уровне операции или сообщения, так что пока часть преимуществ детализированной WS-Security при использовании с клиентом Axis2 теряется.

Если хранить конфигурацию Rampart отдельно от WSDL, как это рекомендуется, необходимо применять эту же конфигурацию для описания сервиса. В листинге 2 показан код клиента, используемый для этой цели в примере приложения. Он вызывает метод applyPolicy() для добавления в определение сервиса политики, содержащей конфигурацию Rampart.

Листинг 2. Настройка операций со стороны клиента
// Создание заглушки клиента
String target = args[0] + "://" + args[1] + ":" + args[2] + args[3];
System.out.println("Connecting to " + target);
LibraryGranularStub stub = new LibraryGranularStub(target);

// Настройка и вызов модуля Rampart
ServiceClient client = stub._getServiceClient();
client.getAxisService().applyPolicy(loadPolicy("rampart-client-policy.xml"));
client.engageModule("rampart");

// Задание имени пользователя и пароля для запросов, в которых они используются
Options options = client.getOptions();
options.setUserName("libuser");
options.setPassword("books");

Код из листинга 2 задает имя пользователя и пароль в опциях ServiceClient, что означает, что они определены для всех операций, использующих этот сервис, даже если используются только в рамках одной операции. В отличие от привлечения модуля Rampart для всех операций, задание параметров имени пользователя и пароля таким способом не причиняет никакого вреда - значения используются лишь тогда, когда Rampart должен сформировать UsernameToken, а в остальных случаях игнорируются.

Документ политики, содержащий конфигурацию Rampart, показан в листинге 3. Это та же политика, которая применялась в статье Подпись и шифрование с помощью Axis2 WS-Security, но теперь она выделена в отдельный документ.

Листинг 3. Политика настройки клиента Rampart
<wsp:Policy 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>

      <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy"> 
        <ramp:user>clientkey</ramp:user>
        <ramp:passwordCallbackClass
          >com.sosnoski.ws.library.adb.PWCBHandler</ramp:passwordCallbackClass>

        <ramp:signatureCrypto>
          <ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
            <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type"
              >JKS</ramp:property>
            <ramp:property name="org.apache.ws.security.crypto.merlin.file"
              >client.keystore</ramp:property>
            <ramp:property
              name="org.apache.ws.security.crypto.merlin.keystore.password"
              >nosecret</ramp:property>
          </ramp:crypto>
        </ramp:signatureCrypto>

      </ramp:RampartConfig>

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

Генерацией кода сервера и клиента из WSDL, компиляцией кода и генерацией файла сервиса AAR управляет файл Ant build.xml, включенный в код загрузки. Он же копирует политику настройки Rampart (она присутствует в загрузке как файл rampart-client-policy.xml в корневом каталоге) в classpath клиента и выполняет некоторую обработку на стороне сервера, которая обсуждаются в следующем разделе.


Со стороны сервера

Если нужно хранить настройки Rampart со стороны сервера вне WSDL (как правило, это очень хорошая идея!), включите их в файл services.xml. В предыдущих статьях мы показали, как это сделать для полной конфигурации WS-SecurityPolicy, включающей конфигурацию Rampart, и применить к сервису в целом. На этот раз в services.xml добавляется только политика настройки Rampart, и делается это на уровне операции.

Документ политики, содержащий конфигурацию Rampart, показан в листинге 4. Как и ее клиентский эквивалент, это та же политика, которая применялась в статье Подпись и шифрование с помощью Axis2 WS-Security, но теперь она выделена в отдельный документ.

Листинг 4. Политика настройки сервера Rampart
<wsp:Policy 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>

      <ramp:RampartConfig xmlns:ramp="http://ws.apache.org/rampart/policy"> 
        <ramp:user>serverkey</ramp:user>
        <ramp:passwordCallbackClass
          >com.sosnoski.ws.library.adb.PWCBHandler</ramp:passwordCallbackClass>

        <ramp:signatureCrypto>
          <ramp:crypto provider="org.apache.ws.security.components.crypto.Merlin">
            <ramp:property name="org.apache.ws.security.crypto.merlin.keystore.type"
              >JKS</ramp:property>
            <ramp:property name="org.apache.ws.security.crypto.merlin.file"
              >server.keystore</ramp:property>
            <ramp:property
              name="org.apache.ws.security.crypto.merlin.keystore.password"
              >nosecret</ramp:property>
          </ramp:crypto>
        </ramp:signatureCrypto>

      </ramp:RampartConfig>

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

Ant build.xml использует программуPolicyTool, включенную в код загрузки, для слияния политики из листинга 4 (присутствует в загрузке как rampart-server-policy.xml в корневом каталоге) в services.xml. Измененный файл services.xml показан в в листинге 5 (он отредактирован с учетом ширины и длины страницы):

Листинг 5. Services.XML после добавлений
<serviceGroup>
  <service name="library-granular">
    <messageReceivers>
      <messageReceiver class=
        "com.sosnoski.ws.library.adb.LibraryGranularMessageReceiverInOut"
        mep="http://www.w3.org/ns/wsdl/in-out"/>
    </messageReceivers>
    <parameter name="ServiceClass"
      >com.sosnoski.ws.library.adb.LibraryGranularImpl</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>.../getBookResponse</outputActionMapping>
    </operation>
    <operation mep="http://www.w3.org/ns/wsdl/in-out" name="getBooksByType"
      namespace="http://ws.sosnoski.com/library/wsdl">
      <actionMapping>urn:getBooksByType</actionMapping>
      <outputActionMapping>.../getBooksByTypeResponse</outputActionMapping>

<module ref="rampart"/>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu=
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <wsp:ExactlyOne>
  <wsp:All>

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

    </ramp:RampartConfig>

  </wsp:All>
  </wsp:ExactlyOne>
</wsp:Policy>
  </operation>
    <operation mep="http://www.w3.org/ns/wsdl/in-out" name="addBook" 
    namespace="http://ws.sosnoski.com/library/wsdl">
      <actionMapping>urn:addBook</actionMapping>
      <outputActionMapping>
        http://ws.sosnoski.com/library/wsdl/Library/addBookResponse
      </outputActionMapping>

<module ref="rampart"/>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy" xmlns:wsu=
    "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
  <wsp:ExactlyOne>
  <wsp:All>

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

    </ramp:RampartConfig>

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

Простой способ добавления политики в services.xml

В статье Основы стандарта Axis2 WS-Security был представлен инструмент для добавления политик и ссылок модуля в сгенерированный файл services.xml, который исключает необходимость редактировать этот файл вручную каждый при восстановлении своего кода на стороне сервера. В этой статье используется усовершенствованная версия этого инструмента, которая позволяет вносить дополнения в конфигурацию сервиса на уровне операций, причем сразу несколько дополнений за раз. Усовершенствованная версия — это com.sosnoski.ws.PolicyTool; исходный и двоичный код находится в каталоге policytool кода загрузки. Инструкции см. в файле readme.txt в этом же каталоге.

Из листинга 5 видно, что ссылка на модуль Rampart и копия политики конфигурации сервера добавлены к определениям двух операций, использующих WS-Security, getBooksByType и addBook. Эти изменения настраивают сервис так, чтобы Rampart использовался только для этих двух операций и чтобы использовались заданные параметры настройки доступа к ключам и сертификатам Rampart.

Собрав и установив сгенерированный файл AAR в экземпляр сервера Axis2, вы увидите результат на странице Administration/Available Services, где перечислены модули, задействованные в каждой операции, определенной для сервиса. Если же запустить код клиента и контролировать обмен сообщениями (с использованием такого инструмента, как TCPMon, который описан в статье Основы стандарта Axis2 WS-Security), то можно убедиться, что защита работает, как следует:

  • заголовки WS-Security в сообщениях getBook отсутствуют;
  • в сообщении запроса getBooksByType имеется заголовок WS-Security с UsernameToken;
  • в сообщении запроса addBook (но не ответа) имеется заголовок WS-Security с подписями.

Ограничения Axis2/Rampart

В настоящее время (то есть в текущей версии Axis2 1.5 и черновой сборке Rampart) Axis2 и Rampart могут обрабатывать простые конфигурации WS-SecurityPolicy, встроенные в WSDL, включая детальные политики, определенные на уровне операций или сообщений. Однако некоторые конфигурации, проверенные для этой статьи, с Axis2/Rampart не работают. Например, попытка задать политику UsernameToken для операции addBook (в дополнение к политике подписи входного сообщения) привела к ошибке, явно связанной с шифрованием в коде Rampart (несмотря на то, что шифрование вообще не используется). Исходя из этого опыта и некоторых сообщений о проблемах, можно сделать вывод, что обработка Axis2/Rampart WS-SecurityPolicy хороша для простых конфигураций, отражающих распространенные сценарии использования, но чревата ошибками при попытках применения к необычным комбинациям.

Другая проблема заключается в том, что издержки использования Rampart на сервере всегда будут проявляться при обработке как запросов, так и ответов, даже если WS-Security используется только для одного из сообщений (как говорилось в статье Высокая цена (WS-)Security). На стороне клиента ситуация еще хуже – потому что на клиентском компьютере Rampart в настоящее время может применяться только целиком, так что если WS-Security используется для любой операции, приходится мириться с накладными расходами Rampart в каждой операции.

Наконец, обработка WS-Policy Axis2/Rampart на сегодняшний день не поддерживает альтернативные варианты политики. Альтернативы ― одна из основных особенностей WS-Policy, которая позволяет сервису предоставлять клиентам выбор из двух или более приемлемых конфигураций, используемых при доступе к сервису. Реализация политики Axis2/Rampart не поддерживает эту функцию, игнорируя все альтернативы, за исключением первой.


Что дальше

В этой и трех предыдущих статьях цикла Web-сервисы Java охвачены все основные вопросы обработки WS-Security и WS-SecurityPolicy в Axis2/Rampart, включая проблемы производительности. Далее мы рассмотрим, как другие системы Web-сервисов Java работают с WS-Security и WS-SecurityPolicy, но сначала остановимся на паре других аспектов Axis2.

Одной из проблем, которая имеет важное значение для многих организаций, это поддержка Java Architecture для Binding XML (JAXB) 2.X. JAXB 2.X - это официальный стандарт Java для привязки XML-данных, и хотя альтернативы с открытым исходным кодом предлагают определенные преимущества, некоторые организации желают придерживаться стандарта. В следующей статье мы рассмотрим, как можно использовать привязку данных JAXB 2.X с Axis2, и сопоставим ее другими способами привязки данных, поддерживаемых Axis2.


Загрузка

ОписаниеИмяРазмер
Исходный код для этой статьиj-jws7.zip29 КБ

Ресурсы

Научиться

Получить продукты и технологии

  • Apache Axis2: загрузите последнюю версию Axis2.

Комментарии

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=Технология Java, SOA и web-сервисы, Open source
ArticleID=782926
ArticleTitle=Web-сервисы Java: Детальное использование WS-Security
publish-date=12262011