 | Уровень сложности: сложный Борис Люблинский, разработчик, CNA Insurance
11.07.2007 Реализация Web-сервисов требует внедрения нескольких уровней защиты, включая защиту обмена информацией, защиту доступа к оконечным точкам Web-сервисов и передачу идентификационной информации между потребителем сервиса и его реализацией. В данной статье рассматривается передача идентификационной информации. Вы узнаете о роли передачи идентификационной информации в общей структуре системы защиты Web-сервисов и о ее поддержке в WebSphere® Application Server (WAS) 6.1, как декларативной, так и программной. Вы узнаете также о том, как данная реализация поддерживает защищенную передачу информации между средами .NET и WebSphere.
Передача идентификационной информации
Типичная реализация системы защиты Web-сервисов имеет дело с защищенным доступом к оконечной точке Web-сервисов (рисунок 1). Это можно сделать при помощи одного из следующих методов:
-
Transport-level invocation security (Защита вызовов процедур на транспортном уровне). Это широко распространенный подход, особенно при реализации Web-сервисов поверх HTTP, который может варьироваться от простой базовой реализации до взаимной аутентификации на базе сертификатов. Этот подход обычно не очень хорошо масштабируется на поддержку идентификации реального пользователя; поэтому здесь преобладает идентификация приложения. Идентификация приложения обычно реализуется на основе специальных "учетных записей приложений" или на сертификатах приложений. В обоих случаях Web-сервис настраивается на аутентификацию запросов и их прием только от ограниченного набора приложений. Проблема данного метода состоит в том, что поддержка передачи идентификационной информации о пользователе требует присутствия в приложении-потребителе сервиса информации обо всех потенциальных пользователях в виде пар пользователь/пароль или пользовательских сертификатов. При изменении контингента пользователей обслуживание этой информации становится очень сложным. Кроме того, защита на транспортном уровне является по своей сути защитой типа точка-точка. Введение промежуточных звеньев в обмен информацией между сервисами делает реализацию защиты на транспортном уровне чрезвычайно сложной.
-
Certificates-based Web services security (Защита Web-сервисов на основе сертификатов). В отличие от реализации защиты на транспортном уровне, при которой устанавливаются доверенные взаимодействия только по каналу точка-точка, решения, применяющие защиту Web-сервисов (см. раздел "Ресурсы"), позволяют сертификатам перемещаться внутри самого SOAP-сообщения. Здесь защита реализуется на уровне сообщений, а не на транспортном уровне, что позволяет передавать сообщения через промежуточные звенья с сохранением доверенных взаимодействий между потребителем сервиса и его провайдером. Аналогично защите на транспортном уровне, это решение обычно основано на идентификации приложений, а не пользователей.
Рисунок 1. Типичная реализация системы защиты Web-сервисов с защитой оконечной точки
Защита доступа к оконечной точке сервиса хорошо работает во многих ситуациях, но для реализаций, где для Web-сервиса важно знать идентификационную информацию о пользователе, инициировавшем конкретный запрос, требуется другой подход. Например, сервис доступа к банковскому счету должен точно знать, кто этот пользователь, чтобы предоставить ему доступ к конкретному счету. Связывание пользователя с данным потоком выполнения является фундаментом основанной на ролях системы защиты, требуемой многими реализациями Web-сервисов.
К счастью, маркер защиты user/binary (пользователь/бинарный), определенный стандартом WS-Security (см. раздел "Ресурсы"), позволяет передачу идентификационной информации о пользователе в реализацию Web-сервиса в качестве части SOAP-сообщения (SOAP-заголовка). Механизм передачи идентификационной информации может использоваться как собственно механизм передачи идентификационной информации, так и как механизм защиты доступа к оконечной точке или совместно с системой защиты доступа к оконечной точке сервиса, описанной ранее. Комбинирование двух подходов обеспечивает самое надежное решение, особенно в случаях, когда к реализации Web-сервиса могут обращаться как аутентифицированные, так и не аутентифицированные пользователи. Ссылка на пример кода описанных в данной статье методик приводится в разделе "Загрузка".
Поддержка передачи идентификационной информации пользователя в WebSphere Application Server 6.1
WebSphere Application Server 6.1 содержит глобальный обработчик системы защиты Web-сервиса (global security handler) вместе с редактором конфигураций Web-сервисов. Это позволяет декларативно реализовать передачу идентификационной информации. Есть три базовых механизма:
- Маркер username (имя пользователя) (см. раздел "Ресурсы").
- LTPA-маркер (Lightweight Third Party Authentication) (см. раздел "Ресурсы") (WAS-маркер двоичной идентичности).
- Пользовательский двоичный маркер (см. раздел "Ресурсы").
Все механизмы передачи идентификационной информации могут быть реализованы при помощи простых настроек (декларативно) на стороне провайдера сервиса (используя webContent/WEB-INF/webservices.xml) и на стороне клиента (используя webContent/WEB-INF/web.xml). Последовательность действий для таких настроек такова (см. раздел "Ресурсы"):
- Добавить маркер защиты для конфигурации генератора запроса.
- Добавить соответствующий генератор маркера для указанного маркера защиты в конфигурации связей генератора запроса защиты.
- Добавить требуемый маркер защиты в настройках конфигурации сервиса потребителя запроса.
- Добавить соответствующего потребителя маркера для указанного требуемого маркера защиты в настройках конфигурации связей потребителя запроса.
Эти настройки могут быть выполнены во время разработки (при помощи программы Application Server Toolkit (AST) 6.1, являющейся частью дистрибутива WebSphere Application Server 6.1). Ссылки на подробную информацию о настройках для маркеров username и LTPA приведены в разделе "Ресурсы". Кроме того, некоторые настройки Web-сервисов могут быть сделаны при помощи консоли администратора WebSphere Application Server. Преимуществом использования консоли администратора для настройки системы защиты является то, что в этом случае разработчик Web-сервиса (клиента) не беспокоится о поддержке системы защиты; это делается во время развертывания на основе требований общей корпоративной системы защиты. К сожалению, в действительности консоль администратора не позволяет настраивать маркер Web-сервисов. Единственной реализованной в настоящее время поддержкой является способность модифицировать процесс создания маркера (если это было определено во время разработки). Такая, весьма ограниченная, функциональность делает использование консоли администратора непрактичным.
Описанные выше конфигурации используются глобальным обработчиком системы защиты WebSphere Application Server, который создает заголовок системы защиты, обеспечивающий передачу идентификационной информации пользователя. В случае маркера username код этого заголовка выглядит примерно так, как показано в листинге 1.
Листинг 1. Заголовок системы защиты, основанной на базовой аутентификации
<wsse:Security soapenv:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>alice</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-
profile-1.0#PasswordText">alicealice</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
|
В случае LTPA-маркера код заголовка выглядит примерно так, как показано в листинге 2.
Листинг 2. Заголовок системы защиты, основанной на LTPA-маркере
<wsse:Security soapenv:mustUnderstand="1"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:BinarySecurityToken ValueType="wsst:LTPA"
xmlns:wsst="http://www.ibm.com/websphere/appserver/tokentype/5.0.2">
hPKZK+HIjr0+vMVFldf7VcF9e4jAnUF1bbqC5+GlbjLQpZJUXyh4SQwJKPhHYwYf6bJZP7I5s
XcE8B4Wsowt81bdNCxXVVMGWFs1JbQ5CbLMOkXwgTyWw3Xbrl9iInNrM+ta/gUm7bcDPs4wjD
86FZilEZIv80DbewgZcPelpfA3kvyEp/X20/4RfE1fmEe816kQfQ1HWouFXlws6vI3pLJ+Nmk
U0a/9xYH6ERbPx7qjXu5YnvbaQHI9HCfLdOZZdNanjnC+OJaN9VnYw1rfzEYDqIBntB6mn4qN
9/X88l+amsYZA808SAqOdO8ie9i1V7IsztBJJM7kQ+cqb07Dtg==
</wsse:BinarySecurityToken>
</wsse:Security>
|
Использование поддержки декларативной защиты делает реализацию передачи идентификационной информации в Web-сервисах очень простой - не требуется никакого программирования. За эту простоту приходится платить. Из-за декларативной природы реализации заголовок системы защиты не отражается в определении сервиса (файл Web Service Definition Language), что затрудняет передачу требований системы защиты между потребителем и провайдером. Кроме того, глобальный заголовок системы защиты после настройки становится обязательным для всех пользователей этого сервиса при использовании декларативной передачи идентификационной информации пользователя. Иными словами, невозможно одновременно поддерживать анонимных и аутентифицированных клиентов сервиса, если используется декларативная передача идентификационной информации. Также, невозможно работать с отличающимися клиентами, одни из которых используют базовую аутентификацию, а другие - LTPA-маркеры для передачи идентификационной информации. В данных конфигурациях не поддерживается смешанная среда (использующая WebSphere Application Server Version 5 и Version 6); даже одинаковый механизм идентификации (например, LTPA-маркер) не может поддерживаться для этих конфигураций. Хотя сам маркер не меняется в реализациях WebSphere Application Server, каждая версия использует различные спецификации системы защиты Web-сервисов и, следовательно, различные пространства имен и форматы заголовка системы защиты. Для поддержки различных схем передачи идентификационной информации в реализациях декларативной системы защиты нужно несколько адресов URL для провайдера сервиса.
Данному подходу присущи также и другие ограничения; например, глобальный заголовок системы защиты поддерживается только в том случае, если клиент и реализация сервиса являются частью J2EE-контейнера (Java 2 Platform, Enterprise Edition). Для автономных потребителей сервисов не поддерживается даже базовая аутентификация.
Преодолению этих ограничений может способствовать программная реализация передачи идентификационной информации пользователя, описываемая далее.
Программная реализация передачи идентификационной информации пользователя
При программной реализации передачи идентификационной информации пользователя заголовок системы защиты должен быть добавлен в определение сервиса. В нашем случае это очень простой сервис echo.
В листинге 3 приведен WSDL-файл (Web Service Definition Language) для простого сервиса echo с заголовком системы защиты.
Листинг 3. WSDL-файл для сервиса echo с заголовком системы защиты
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://services.cna.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:intf="http://services.cna.com"
xmlns:impl="http://services.cna.com"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity
-secext-1.0.xsd">
<wsdl:types>
<schema elementFormDefault="qualified"
targetNamespace="http://services.cna.com"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:impl="http://services.cna.com" xmlns:intf="http://services.cna.com"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<element name="echo">
<complexType>
<sequence>
<element name="request" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
<element name="echoResponse">
<complexType>
<sequence>
<element name="echoReturn" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
</element>
</schema>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:import namespace="http://docs.oasis-open.org/wss/2004/01/oasis-200401
-wss-wssecurity-secext-1.0.xsd" schemaLocation="security.xsd"/>
</xsd:schema>
</wsdl:types>
<wsdl:message name="echoRequest">
<wsdl:part name="loginHeader" element="wsse:Security"/>
<wsdl:part name="parameters" element="intf:echo"/>
</wsdl:message>
<wsdl:message name="echoResponse">
<wsdl:part name="parameters" element="intf:echoResponse"/>
</wsdl:message>
<wsdl:portType name="EchoService">
<wsdl:operation name="echo">
<wsdl:input name="echoRequest" message="intf:echoRequest"/>
<wsdl:output name="echoResponse" message="intf:echoResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="EchoServiceSoapBinding" type="intf:EchoService">
<wsdlsoap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="echo">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="echoRequest">
<wsdlsoap:header message="intf:echoRequest" part="loginHeader"
use="literal" encodingStyle="literal">
</wsdlsoap:header>
<wsdlsoap:body parts="parameters" use="literal"/>
</wsdl:input>
<wsdl:output name="echoResponse">
<wsdlsoap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="EchoServiceService">
<wsdl:port name="EchoService" binding="intf:EchoServiceSoapBinding">
<wsdlsoap:address
location="http://localhost:9080/echoService/services/EchoService"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
|
На базе этого WSDL-файла мы сгенерировали реализацию сервиса, используя программу Application Server Toolkit (AST) (листинг 4).
Листинг 4. Реализация сервиса echo
package com.cna.services;
import javax.xml.rpc.handler.MessageContext;
import javax.xml.rpc.handler.soap.SOAPMessageContext;
import javax.xml.rpc.server.ServiceLifecycle;
import javax.xml.rpc.server.ServletEndpointContext;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;
import com.cna.service.header.securityCredentials;
import com.cna.service.header.securityHeader;
public class EchoServiceSoapBindingImpl implements EchoService, ServiceLifecycle{
public void init(Object ctx){
System.out.println("Inside Service init method, context is " + ctx);
ServletEndpointContext sC = (ServletEndpointContext)ctx;
securityCredentials.printServletCredentials(sC);
MessageContext context = sC.getMessageContext();
try{
SOAPMessageContext smc = (SOAPMessageContext)context;
SOAPMessage sMessage = smc.getMessage();
System.out.println("SOAP message is ");
sMessage.writeTo(System.out);
System.out.println("\n");
}
catch(Exception e){}
}
public EchoResponse echo(SOAPElement loginHeader, Echo parameters)
throws java.rmi.RemoteException {
String request = parameters.getRequest();
System.out.println("Inside echo service " + request);
// Сбросить идентификационную информацию пользователя в исходное состояние
securityHeader.processHeader(loginHeader);
securityCredentials.printCredentials();
// Возврат
EchoResponse responce = new EchoResponse();
responce.setEchoReturn("return ");
return responce;
}
public void destroy(){
System.out.println("Inside Service destroy method");
}
}
|
В сгенерированную AST реализацию был добавлен код для:
- Наследования сгенерированного класса для интерфейса ServiceLifecycle. Это требует реализации двух методов -
init, вызываемого конвейером Web-сервисов прямо перед активизацией сервиса, и destroy, вызываемого конвейером Web-сервисов сразу после активизации сервиса.
- Реализации метода
init для получения и вывода идентификационной информации пользователя перед активизацией сервиса и содержимого входящего SOAP-сообщения.
- Реализации метода
destroy для вывода документа, указывающего, что был активизирован метод.
- Реализации метода сервиса echo, который:
- Обрабатывает заголовок системы защиты (см. "Реализация системы идентификации пользователей в WebSphere Application Server") и сбрасывает идентификационную информацию пользователя на основе содержимого заголовка.
- Выводит информацию о полномочиях нового пользователя.
- Создает и возвращает ответ сервиса.
Фактическая реализация получения и вывода полномочий пользователя выполняется с использованием специализированного класса securityCredentials, показанного в листинге 5.
Листинг 5. Получение и создание полномочий пользователя
package com.cna.service.header;
import java.security.Principal;
import java.util.Set;
import javax.security.auth.Subject;
import javax.xml.rpc.server.ServletEndpointContext;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.cred.WSCredential;
public class securityCredentials {
public static void printServletCredentials(ServletEndpointContext ctx){
String tName = Thread.currentThread().getName();
System.out.println("Executing on the thread " + tName);
Principal userPrinciple = ctx. getUserPrincipal();
System.out.println("user is " + userPrinciple);
}
public static void printCredentials(){
String tName = Thread.currentThread().getName();
System.out.println("Executing on the thread " + tName);
try{
Subject caller_security = WSSubject.getCallerSubject();
Subject run_security = WSSubject.getRunAsSubject();
if (caller_security != null){
// Получить все полномочия из субъекта системы защиты
Set security_credentials =
caller_security.getPublicCredentials(WSCredential.class);
// Получить первые полномочия
WSCredential security_credential =
(WSCredential)security_credentials.iterator().next();
String user = (String) security_credential.getSecurityName();
System.out.println("Caller Identity " + user);
}
if (run_security != null){
// Получить все полномочия из субъекта системы защиты
Set security_credentials =
run_security.getPublicCredentials(WSCredential.class);
// Получить первые полномочия
WSCredential security_credential =
(WSCredential)security_credentials.iterator().next();
String user = (String) security_credential.getSecurityName();
System.out.println("Execution Identity " + user);
}
}
catch (Exception e){
System.out.println("Error obtaining credentials");
e.printStackTrace();
}
}
}
|
Этот класс реализует два метода:
- Метод
printServletCredentials выводит информацию о полномочиях, связанных с контекстом сервлета. Она используется в методе init интерфейса ServiceLifecycle для получения полномочий начальной активизации.
- Метод
printServletCredentials извлекает полномочия WebSphere Application Server, связанные с текущим потоком выполнения, и выводит их.
- Реализует метод
destroy для вывода документа, указывающего на то, что метод был активизирован.
Метод PrintCredentials использует интерфейсы прикладного программирования (application program interfaces - API) WebSphere Application Server 6.1, WSSubject и WSCredential для получения имени пользователя, чьи полномочия используются для выполнения потока.
 |
Реализация идентичности пользователя в WebSphere Application Server
WebSphere Application поддерживает в приложении две идентичности:
-
caller identity, то есть, входящий пользователь ресурса
-
runAs identity, то есть, идентичность, используемая для активизации потока данных ресурса
В следующем сценарии предполагается, что в сервлете по умолчанию настроена runAs, а идентичности caller и runAs одинаковы:
- Browser -- user1 > servlet -- user1 > EJB
В предыдущем случае оба метода, WSSubject.getCallerSubject() и WSSubject.getRunAsSubject(), возвращают идентичность user1.
Если настройка runAs в сервлете не является настройкой по умолчанию, а установлена в конкретного пользователя, например, user2, то идентичности caller и runAs в сервлете не одинаковы, что показано ниже:
- Browser -- user1 > servlet -- user2 > EJB
В этом случае WSSubject.getCallerSubject() возвращает user1, а WSSubject.getRunAsSubject() возвращает user2. user2 используется для исходящего вызова из сервлета.
|
|
Реализация класса loginSecurityHeader, используемая в сервисе, представлена в листинге 6.
Листинг 6. Программная реализация заголовка
package com.cna.service.header;
import java.util.Iterator;
import java.util.Set;
import javax.security.auth.Subject;
import javax.security.auth.login.LoginContext;
import javax.security.auth.login.LoginException;
import javax.xml.soap.Name;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPFactory;
import org.apache.xml.serialize.OutputFormat;
import org.apache.xml.serialize.XMLSerializer;
import com.ibm.websphere.security.WSSecurityException;
import com.ibm.websphere.security.auth.WSSubject;
import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl;
import com.ibm.websphere.security.cred.WSCredential;
import com.ibm.ws.webservices.engine.encoding.Base64;
public class securityHeader {
private static String LTPAns = "wsst";
private static String LTPAid = ":LTPA";
private static String LTPAURL =
"http://www.ibm.com/websphere/appserver/tokentype/5.0.2";
private static String passwordType =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-
profile-1.0#PasswordText";
private static String SecurityURL =
"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd";
private static String SOAPEncURL = "htp://schemas.xmlsoap.org/soap/encoding/";
private static String SOAPEnvURL = "http://schemas.xmlsoap.org/soap/envelope/";
private static String XMLSchemaURL = "http://www.w3.org/2001/XMLSchema";
private static String XMLSchemaInsURL = "http://www.w3.org/2001/XMLSchema-instance";
// Создать заголовок LTPA-маркера
public static SOAPElement createLTPAHeader(){
// Сначала попробовать получить сам маркер
byte[] token = getSecurityToken();
if(token == null)
return null;
// Теперь попробовать создать заголовок
SOAPElement header = null;
try{
// Создать Element заголовка
SOAPFactory sFactory = SOAPFactory.newInstance();
Name headerName = sFactory.createName("Security","wsse",SecurityURL);
header = sFactory.createElement(headerName);
header.addNamespaceDeclaration("soapenc",SOAPEncURL);
header.addNamespaceDeclaration("xsd",XMLSchemaURL);
header.addNamespaceDeclaration("xsi",XMLSchemaInsURL);
Name mustName = sFactory.createName("mustUnderstand","soapenv",SOAPEnvURL);
header.addAttribute(mustName,"1");
// Создать и добавить Element двоичного маркера
Name binaryTokenName = sFactory.createName("BinarySecurityToken","wsse",
SecurityURL);
SOAPElement binaryToken = sFactory.createElement(binaryTokenName);
header.addChildElement(binaryToken);
// Заполнить маркер
binaryToken.addNamespaceDeclaration(LTPAns,LTPAURL);
Name attrName = sFactory.createName("ValueType");
binaryToken.addAttribute(attrName,LTPAns+LTPAid);
String stoken = Base64.encode(token);
binaryToken.addTextNode(stoken);
}
catch(Exception e){
System.out.println("Error building LTPA security header");
e.printStackTrace();
}
return header;
}
// Создать заголовок BasicAuth
public static SOAPElement createBasicAuth(String user, String password){
// Проверить наличие полномочий
if((user == null) || (password == null)){
return null;
}
// Теперь попробовать создать заголовок
SOAPElement header = null;
try{
// Создать Element заголовка
SOAPFactory sFactory = SOAPFactory.newInstance();
Name headerName = sFactory.createName("Security","wsse",SecurityURL);
header = sFactory.createElement(headerName);
header.addNamespaceDeclaration("soapenc",SOAPEncURL);
header.addNamespaceDeclaration("xsd",XMLSchemaURL);
header.addNamespaceDeclaration("xsi",XMLSchemaInsURL);
Name mustName = sFactory.createName("mustUnderstand","soapenv",SOAPEnvURL);
header.addAttribute(mustName,"1");
// Создать и добавить Element маркера userName
Name userTokenName = sFactory.createName("UsernameToken","wsse",SecurityURL);
SOAPElement userToken = sFactory.createElement(userTokenName);
header.addChildElement(userToken);
// Заполнить маркер
Name userElementName = sFactory.createName("Username","wsse",SecurityURL);
Name passwordElementName = sFactory.createName("Password","wsse",
SecurityURL);
SOAPElement userElement = sFactory.createElement(userElementName);
userElement.addTextNode(user);
SOAPElement passwordElement = sFactory.createElement(passwordElementName);
Name attrName = sFactory.createName("Type");
passwordElement.addAttribute(attrName,passwordType);
passwordElement.addTextNode(password);
userToken.addChildElement(userElement);
userToken.addChildElement(passwordElement);
}
catch(Exception e){
System.out.println("Error building Basic Auth security header");
e.printStackTrace();
}
return header;
}
// Обработать заголовок системы защиты
public static void processHeader(SOAPElement header){
try{
//Сначала вывести его
try{
OutputFormat ouf = new OutputFormat();
ouf.setIndenting(true);
XMLSerializer serializer = new XMLSerializer(System.out,ouf);
serializer.serialize(header);
System.out.println(" ");
}
catch(Exception e){
e.printStackTrace();
}
// Проверить тип маркера
SOAPFactory sFactory = SOAPFactory.newInstance();
Name binaryTokenName = sFactory.createName("BinarySecurityToken","wsse",
SecurityURL);
Name userTokenName = sFactory.createName("UsernameToken","wsse",SecurityURL);
// Это двоичный маркер?
Iterator tokens = header.getChildElements(binaryTokenName);
if(tokens != null){
while(tokens.hasNext()){
SOAPElement binaryToken = (SOAPElement)tokens.next();
// Убедиться, что это LTPA
String tType = binaryToken.getAttribute("ValueType");
if((tType == null) || !tType.endsWith(LTPAid))
continue;
String stoken = binaryToken.getValue();
byte[] token = Base64.decode(stoken);
setSecurityContext(token);
return;
}
}
// Это маркер Basic Auth?
tokens = header.getChildElements(userTokenName);
if((tokens != null) && (tokens.hasNext())){
// Обработать маркер Basic Auth
SOAPElement userToken = (SOAPElement)tokens.next();
// Получить имя и пароль
Name userElementName = sFactory.createName("Username","wsse",
SecurityURL);
Name passwordElementName = sFactory.createName("Password","wsse",
SecurityURL);
Iterator users = userToken.getChildElements(userElementName);
Iterator passwords = userToken.getChildElements(passwordElementName);
if((users != null) && (users.hasNext()) &&
(passwords != null) && (passwords.hasNext())){
String user = ((SOAPElement)users.next()).getValue();
String password = ((SOAPElement)passwords.next()).getValue();
setSecurityContext(user,password);
}
return;
}
// Неизвестный маркер, игнорировать
}
catch(Exception e){
System.out.println("Error processing security header");
e.printStackTrace();
}
}
// Получить маркер системы защиты
private static byte[] getSecurityToken(){
byte[] token = null;
try{
// Получить текущий субъект защиты
Subject security_subject = WSSubject.getRunAsSubject();
if (security_subject != null){
// Получить все полномочия из субъекта защиты
Set security_credentials =
security_subject.getPublicCredentials(WSCredential.class);
// Получить первые полномочия
WSCredential security_credential =
(WSCredential)security_credentials.iterator().next();
String user = (String) security_credential.getSecurityName();
// Получить маркер системы защиты
token = security_credential.getCredentialToken();
System.out.println("My data from the Caller credential is: " +
user + " security token is: ");
System.out.println(token);
System.out.println("\n");
}
}
catch (Exception e){
System.out.println("Error obtaining token");
e.printStackTrace();
}
return token;
}
private static void setSecurityContext(byte[] token){
if(token == null){
System.out.println("Cannot create LoginContext. No token");
return;
}
LoginContext lc = null;
// Создать новый контекст для регистрации
try {
lc = new LoginContext("WSLogin",new WSCallbackHandlerImpl(token));
}
catch (LoginException le) {
System.out.println("Cannot create LoginContext. " + le.getMessage());
return;
}
catch(SecurityException se) {
System.out.println("Cannot create LoginContext." + se.getMessage());
return;
}
// Зарегистрироваться с новым контекстом
try{
lc.login();
}
catch(LoginException le){
System.out.println("Fails to Login. " + le.getMessage());
return;
}
// Получить субъект защиты
Subject security_subject = lc.getSubject();
// Установить субъект защиты
try{
WSSubject.setRunAsSubject(security_subject);
}
catch (WSSecurityException e){
System.out.println("Error Setting security credentials. " + e.getMessage());
}
catch (Exception e){
System.out.println("Error Setting security credentials. " + e.getMessage());
}
}
private static void setSecurityContext(String user, String password){
if((user == null) || (password == null)){
System.out.println("Cannot create LoginContext. No token");
return;
}
LoginContext lc = null;
// Создать новый контекст для регистрации
try {
lc = new LoginContext("WSLogin",new WSCallbackHandlerImpl(user, password));
}
catch (LoginException le) {
System.out.println("Cannot create LoginContext. " + le.getMessage());
return;
}
catch(SecurityException se) {
System.out.println("Cannot create LoginContext." + se.getMessage());
return;
}
// Зарегистрироваться с новым контекстом
try{
lc.login();
}
catch(LoginException le){
System.out.println("Fails to Login. " + le.getMessage());
return;
}
// Получить субъект защиты
Subject security_subject = lc.getSubject();
// Установить субъект защиты
try{
WSSubject.setRunAsSubject(security_subject);
}
catch (WSSecurityException e){
System.out.println("Error Setting security credentials. " + e.getMessage());
}
catch (Exception e){
System.out.println("Error Setting security credentials. " + e.getMessage());
}
}
}
|
Приведенный в листинге 6 класс имеет следующие методы:
-
createLTPAHeader() - Создает заголовок системы защиты (листинг 2) на основе LTPA-маркера. Этот метод использует метод getSecurityToken() этого же класса для получения LTPA-маркера для идентификационной информации текущего пользователя.
-
createBasicAuth(String user, String password) - Создает заголовок системы защиты (листинг 1) на основе информации "имя пользователя/пароль".
-
processHeader(SOAPElement header) - Обрабатывает заголовок системы зашиты и устанавливает runAs identity на основе содержимого заголовка. Этот метод использует методы setSecurityContext(byte token) и setSecurityContext(String user, String password) этого же класса для установки идентичности runAs на основе либо LTPA-маркера, либо "имени пользователя/пароля".
-
getSecurityToken() - Получает LTPA-маркер, соответствующий идентификационной информации текущего пользователя. Здесь используются API WebSphere Application Server 6.1 WSSubject и WSCredential, как в коде для программного получения идентификационной информации пользователя (листинг 4).
-
setSecurityContext(String user, String password) - Устанавливает идентичность пользователя runAs на основе "имени пользователя/пароля". Этот метод использует API WebSphere Application Server 6.1 программной регистрации для получения субъекта защиты и WSSubject.setRunAsSubject API для работы под конкретным пользователем.
-
setSecurityContext(byte token) - Устанавливает идентичность пользователя runAs на основе LTPA-маркера. Этот метод использует API WebSphere Application Server 6.1 программной регистрации для получения субъекта защиты и WSSubject.setRunAsSubject API для работы под конкретным пользователем.
Мы также объединили системы защиты передачи идентификационной информации пользователя и оконечной точки, определив права доступа к URL оконечной точки сервиса. Это осуществляется путем определения защиты в WAR-файле (Web Application Resource) сервиса (листинг 7) и Enterprise Application Resource (EAR), как показано на рисунке 2.
Листинг 7. Конфигурации системы защиты в WAR-файле сервиса
<?xml version="1.0" encoding="UTF-8"?>
<web-app id="WebApp_ID" version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SecureServiceProvider</display-name>
<servlet>
<servlet-name>com_cna_services_EchoServiceSoapBindingImpl</servlet-name>
<servlet-class>com.cna.services.EchoServiceSoapBindingImpl</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<security-constraint>
<display-name>resourceAccess</display-name>
<web-resource-collection>
<web-resource-name>AllResources</web-resource-name>
<url-pattern>\*</url-pattern>
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description></description>
<role-name>ApplicationUsers</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>ApplicationUsers</role-name>
</security-role>
</web-app>
|
Рисунок 2. Конфигурации системы защиты в EAR-файле сервиса
 |
Передача идентификационной информации и защита оконечной точки
На первый взгляд может показаться, что добавление системы защиты оконечной точки к передаче идентификационной информации является излишеством. В некоторой степени передача идентификационной информации является формой защиты - если идентичность не может быть установлена (обработана), запрос будет отклонен. В действительности это не одно и то же.
Передача идентификационной информации разрешает выполнение реализации сервиса с идентификационной информацией пользователя, который активизировал инициированный приложением запрос. Система защиты оконечной точки позволяет ограничить доступ к сервису только для конкретной группы пользователей. Обычно это не реальные пользователи, а "учетные записи приложения". Другими словами, защита оконечной точки устанавливает доверие между потребителями и провайдерами (приложениями) сервиса, тогда как система передачи идентификационной информации разрешает передачу информации пользователя, инициировавшего цепочку запросов.
|
|
Конфигурация системы защиты, показанная в листинге 7 и на рисунке 2, разрешает доступ к оконечной точке сервиса только аутентифицированным пользователям. В данном случае аутентификация пользователя обычно основывается на учетных записях приложения, определенных для доступа к сервису, а не на конкретных пользователях.
На базе того же самого WSDL-файла (листинг 3) были созданы клиент сервиса и простой класс для тестирования сервиса (листинг 9).
Листинг 8. Реализация клиента сервиса
package com.cna.services.tester;
import javax.xml.rpc.Stub;
import javax.xml.soap.SOAPElement;
import com.cna.service.header.loginSecurityHeader;
import com.cna.services.Echo;
import com.cna.services.EchoService;
import com.cna.services.EchoServiceProxy;
public class serviceTester {
public void testServices(){
SOAPElement loginHeader = loginSecurityHeader.createLTPAHeader();
Echo request = new Echo();
request.setRequest("my echo");
EchoServiceProxy portProxy = new EchoServiceProxy();
EchoService port = portProxy.getEchoService();
Stub stub = (Stub)port;
stub._setProperty(Stub.USERNAME_PROPERTY,"bob");
stub._setProperty(Stub.PASSWORD_PROPERTY,"bobbob");
String reply = null;
try{
reply = port.echo(loginHeader,request).getEchoReturn();
}
catch(Exception e){
System.out.println("Error invoking service");
e.printStackTrace();
}
System.out.println("Done invoking service " + reply);
}
}
|
Этот класс использует loginSecurityHeader, представленный в листинге 5, для создания основанного на LTPA заголовка и активизирует сервис echo с этим заголовком и запросом. Кроме того, этот класс устанавливает заголовки базовой аутентификации в HTTP-запросе, для того чтобы пройти через систему защиты Web-контейнера, определенную в оконечной точке сервиса (листинг 7 и рисунок 2).
Простая JSP-страница (JavaServer Pages), активизирующая тестировщик сервиса, приведена в листинге 9.
Листинг 9. Тестовая JSP-страница сервиса echo
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<HTML>
<HEAD>
<%@ page
language="java"
contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"
%>
<jsp:useBean id="serviceTester" scope="session"
class="com.cna.services.tester.serviceTester" />
<META http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<META name="GENERATOR" content="IBM WebSphere Studio">
<TITLE>serviceTester.jsp</TITLE>
</HEAD>
<BODY>
<P>Testing Service ... </P>
<% serviceTester.testServices(); %>
<P>Done </P>
</BODY>
</HTML>
|
Для корректной работы примера поток выполнения должен работать с идентификационной информацией конкретного пользователя в точке активизации сервиса. Сделать это можно путем определения системы защиты Web-контейнера для клиента сервиса, как показано в листинге 10 (WAR-файл клиента сервиса) и на рисунке 3 (EAR-файл клиента сервиса).
Примечание: В файл web.xml WebSphere Application Server V6 для потребителей сервисов были внесены изменения. Информация о сервисе, использовавшаяся в webservices_client.xml, теперь перемещена в web.xml.
Листинг 10. Конфигурации защиты в WAR-файле клиента сервиса
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
id="WebApp_ID" version="2.4"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee
http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">
<display-name>SecureServiceConsumer</display-name>
<servlet>
<description></description>
<display-name>serviceTester</display-name>
<servlet-name>serviceTester</servlet-name>
<jsp-file>/service/tester/serviceTester.jsp</jsp-file></servlet>
<servlet-mapping>
<servlet-name>serviceTester</servlet-name>
<url-pattern>/serviceTester</url-pattern>
</servlet-mapping>
<security-constraint>
<display-name>Everything</display-name>
<web-resource-collection>
<web-resource-name>ALL_Resources</web-resource-name>
<url-pattern>/*</url-pattern>
<http-method>GET</http-method>
<http-method>PUT</http-method>
<http-method>POST</http-method>
</web-resource-collection>
<auth-constraint>
<description></description>
<role-name>RegisteredUsers</role-name>
</auth-constraint>
</security-constraint>
<security-role>
<role-name>RegisteredUsers</role-name>
</security-role>
<service-ref>
<description>WSDL Service EchoServiceService</description>
<service-ref-name>service/EchoServiceService</service-ref-name>
<service-interface>com.cna.services.EchoServiceService
</service-interface>
<wsdl-file>WEB-INF/wsdl/EchoServiceSecurity.wsdl</wsdl-file>
<jaxrpc-mapping-file>WEB-INF/EchoServiceSecurity_mapping.xml
</jaxrpc-mapping-file>
<service-qname xmlns:pfx="http://services.cna.com">
pfx:EchoServiceService</service-qname>
<port-component-ref>
<service-endpoint-interface>com.cna.services.EchoService
</service-endpoint-interface>
</port-component-ref>
</service-ref>
</web-app>
|
Рисунок 3. Настройки защиты в EAR клиента
После установки защиты Web-контейнера при попытке активизировать тестовую JSP-страницу (листинг 9) сервер запросит у пользователя его имя и пароль. При активизации тестовой JSP (листинг 9) пример выполняется полностью и выдает результаты, показанные в листинге 11.
Листинг 11. Результаты активизации сервиса echo из J2EE-клиента
Caller credential is: boris
Inside Service init method
Executing on the thread WebContainer : 1
user is bob
SOAP message is
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Header>
<wsse:Security soapenv:mustUnderstand="1"
xmlns:soapenc="htp://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-wssecurity-secext-1.0.xsd"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<wsse:BinarySecurityToken ValueType="wsst:LTPA"
xmlns:wsst="http://www.ibm.com/websphere/appserver/tokentype/5.0.2">
hPKZK+HIjr3R3oQgnfKX26/EBzZl2H+vfsxbZCMj4NO9Crsuy4Dx73wwavEdkBN6iE2Y5I1B6
/0IgMKvI42PVtPEzwTUBmI3SfEsVm4zLi4NxgYY/8aRT7k3sRG+1sFGikbruwxXJqQhhQ6Owu
YOxVfqWfODHvSVnlGuV/TPUGqY6V48LIEVGu7I2GtZ9iR1RJhfEPAOi+dADp9FGVa+fy0opYUF
M19i++czim6cBKFD+ttqp3LjLBqLG25Zst2FJ3GwAEy21EW5kU+oG5th390CIJGss+phWZFXxS
+RfHnvJ8HsBY1yz0reRvBZ9Y3KkSc2SvMFEfNBjc+rs3cvgw==
</wsse:BinarySecurityToken>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<p61:echo xmlns:p61="http://services.cna.com">
<p61:request>my echo</p61:request>
</p61:echo>
</soapenv:Body>
</soapenv:Envelope>
Inside echo service my echo
Caller Identity bob
Execution Identity boris
Inside Service destroy method
Done invoking service return my echo
|
Как показано в листинге 11, клиент сервиса получает идентификационную информацию текущего пользователя (в данном случае boris) и создает LTPA-маркер, соответствующий этому пользователю. Затем запрос передается сервису. В методе init сервиса пользователем является bob. Причина этого заключается в том, что клиент сервиса использует полномочия пользователя Bob для базовой аутентификации во время активизации оконечной точки сервиса. При активизации оконечной точки сервиса loginSecurityHeader обрабатывает входящий LTPA-маркер и сбрасывает идентификационную информацию о пользователе в boris.
Описанное решение работает также в ситуации с цепочкой активизации сервисов. В этом случае каждый сервис устанавливает идентификационную информацию о пользователе, а затем создает соответствующий маркер для передачи запросов следующему сервису.
Кроме того, реализация заголовка сервиса (листинг 6) работает без изменений в WebSphere Application Server V5.1. Поскольку сам LTPA-маркер не изменился ни в одной из версий между V5.1 и V6.1, описанная в данной статье реализация может также использоваться для достижения совместимости между различными версиями WebSphere Application Server.
Совместимость со средой .NET
Поскольку LTPA-маркеры зависят от версии WebSphere Application Server, они не применимы для среды .NET®. Поэтому предпочтительным подходом к передаче идентификационной информации для .NET-клиента является базовая аутентификация. Web Services Enhancements (WSE) 2.0 предоставляет очень простой API для реализации базовой аутентификации с использованием UserName Token (см. раздел "Ресурсы"). Пример базового кода такой реализации приведен в листинге 12.
Листинг 12. Поддержка маркера UserName в WSE 2.0
using System;
using System.Net;
using Microsoft.Web.Services2.Security.Tokens;
using secureClient.EchoService;
namespace secureClient
{
class secureClient{
static void Main(string[] args){
string request = "my echo request";
EchoServiceServiceWse service = new EchoServiceServiceWse();
service.Url =
"http://localhost:9080/SecureServiceProvider/services/EchoService";
// Установить сетевые полномочия
NetworkCredential credentials = new NetworkCredential("bob","bobbob");
service.Credentials = credentials;
// Создать и установить маркер userName
UsernameToken token = new UsernameToken( "alice", "alicealice",
PasswordOption.SendPlainText);
service.RequestSoapContext.Security.Tokens.Add(token);
string reply = service.echo(request);
}
}
}
|
Этот код создает маркер системы защиты, показанный в листинге 13.
Листинг 13. Маркер UserName, созданный WSE 2.0
<wsse:Security soap:mustUnderstand="1"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-
utility-1.0.xsd"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<wsu:Timestamp wsu:Id="Timestamp-7ffcec19-5e0b-497b-a1d6-130270590788">
<wsu:Created>2006-10-01T02:39:24Z</wsu:Created>
<wsu:Expires>2006-10-01T02:44:24Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken
wsu:Id="SecurityToken-287911b6-1343-4ab1-b28b-1897de103b93"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-
wssecurity-utility-1.0.xsd">
<wsse:Username>alice</wsse:Username>
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-username-token-profile-1.0#PasswordText">alicealice</wsse:Password>
<wsse:Nonce>5UlY0kemIcMYfVB6v5kPtw==</wsse:Nonce>
<wsu:Created>2006-10-01T02:39:25Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
|
Заголовок системы защиты, созданный средой .NET (листинг 13), является подмножеством заголовка системы защиты с маркером username, используемого в WebSphere Application Server V6.1 (листинг 1). Поскольку наша реализация игнорирует не использующиеся элементы заголовка, она будет корректно обрабатывать заголовок, созданный средой времени исполнения .NET.
Поскольку оконечная точка сервиса echo защищена и требует аутентификации, в дополнение к маркеру системы защиты реализация клиента создает сетевые полномочия с соответствующим именем пользователя и паролем, а также добавляет имя в сгенерированный прокси сервиса. Результаты выполнения .NET-клиента представлены в листинге 14.
Листинг 14. Результаты активизации сервиса echo из .Net-клиента
Inside Service init method
user is bob
SOAP message is
<soap:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-
wssecurity-secext-1.0.xsd"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-
wssecurity-utility-1.0.xsd">
<soap:Header>
<wsa:Action/>
<wsa:MessageID>uuid:e4eaa82a-9984-458a-9a8e-a9f0534ebed5</wsa:MessageID>
<wsa:ReplyTo>
<wsa:Address>http://schemas.xmlsoap.org/ws/2004/03/addressing/
role/anonymous</wsa:Address>
</wsa:ReplyTo>
<wsa:To>http://localhost:9080/SecureServiceProvider/services/EchoService</wsa:To>
<wsse:Security soap:mustUnderstand="1">
<wsu:Timestamp wsu:Id="Timestamp-7ffcec19-5e0b-497b-a1d6-130270590788">
<wsu:Created>2006-10-01T02:39:24Z</wsu:Created>
<wsu:Expires>2006-10-01T02:44:24Z</wsu:Expires>
</wsu:Timestamp>
<wsse:UsernameToken
wsu:Id="SecurityToken-287911b6-1343-4ab1-b28b-1897de103b93"
xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-
wss-wssecurity-utility-1.0.xsd">
<wsse:Username>alice</wsse:Username>
<wsse:Password
Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-
username-token-profile-1.0#PasswordText">alicealice</wsse:Password>
<wsse:Nonce>5UlY0kemIcMYfVB6v5kPtw==</wsse:Nonce>
<wsu:Created>2006-10-01T02:39:25Z</wsu:Created>
</wsse:UsernameToken>
</wsse:Security>
</soap:Header>
<soap:Body>
<echo xmlns="http://services.cna.com">
<request>my echo request</request>
</echo>
</soap:Body>
</soap:Envelope>
Inside echo service my echo request
Caller Identity bob
Execution Identity alice
Inside Service destroy method
|
Так же как и для J2EE-клиента, в методе init сервиса пользователем является bob. Причина состоит в том, что именно данный пользователь предоставляется при активизации сервиса. В самой реализации сервиса loginSecurityHeader обрабатывает входящий маркер username и сбрасывает идентификационную информацию о пользователе в alice.
Резюме
В данной статье вы исследовали предложенное программное решение для реализации заголовка системы защиты Web-сервисов, поддерживающее передачу идентификационной информации пользователя. Данная реализация требует несколько больших усилий по сравнению с декларативной поддержкой в WebSphere Application Server V6.1, но предоставляет значительно большую гибкость. Она позволяет поддержку в одной и той же оконечной точке сервиса и не аутентифицированных запросов, а также запросов, придерживающихся различных схем аутентификации. Также, это решение позволяет потребителям сервиса программно определять, использовать ли механизм передачи идентификационной информации, и какой именно механизм. Более того, программная реализация (в отличие от декларативной поддержки) не зависит от транспортного уровня и может быть использована в реализации Web-сервиса, работающего по любому транспортному протоколу. В данной статье вы также узнали, как использовать предложенный код для передачи идентификационной информации из .NET-клиента.
 |
Благодарности
Автор признателен своим коллегам в CNA и IBM, особенно Хьену Чангу (Hyen V Chung), Мэтту ОНилу (Matt ONeal) и Деборе Шеддон (Deborah Shaddon), за обсуждения, которые помогли улучшить эту статью и приведенный в ней код.
Загрузка | Описание | Имя | Размер | Метод загрузки |
|---|
| Код примера реализации для J2EE | ar-userwebcode1.zip | 85KB | HTTP |
|---|
| Код примера для .NET | ar-userwebcode2.zip | 28KB | HTTP |
|---|
Ресурсы - Примите участие в обсуждении материала на форуме.
- Оригинал статьи "User identity propagation in Web service implementation".
-
Самая свежая информация о системе защиты Web-сервисов от комитета OASIS WS-Security.
-
"Передовой опыт работы с Web-сервисами, часть 11: Защита Web-сервисов, часть 1", Холт Адамс (Holt Adams) (developerWorks, март 2004). Передовой опыт реализации защищенных Web-сервисов.
-
"Передовой опыт работы с Web-сервисами, часть 12: Защита Web-сервисов, часть 2", Холт Адамс (Holt Adams) (developerWorks, март 2004). Передовой опыт реализации защищенных Web-сервисов фирмой IBM.
-
"WS-Security Drilldown в Web Services Enhancements 2.0", Дон Смит (Don Smith) (MSDN, август 2004). Прекрасное введение в поддержку системы защиты Web-сервисов в Web Services Enhancements 2.0.
-
"Защита Web-сервисов в WebSphere Application Server V6, часть 1: Введение в архитектуры систем защиты", Тони Кован (Tony Cowan) (IBM WebSphere Developer Technical Journal, март 2006). Обзор поддержки защиты Web-сервисов в WebSphere Application Server V6.
-
"Защита Web-сервисов в WebSphere Application Server V6, часть 2: Использование Username Token и SSL", Ирина Синг (Irina Singh) (IBM WebSphere Developer Technical Journal, апрель 2006). Пошаговое введение в реализацию системы защиты Web-сервисов с использованием маркеров username в WebSphere Application Server V6.
-
"Защита Web-сервисов в WebSphere Application Server V6, часть 4: Использование LTPA-маркера", Арнольд Деспретс (Arnauld Desprets) (IBM WebSphere Developer Technical Journal, июль 2006). Пошаговое введение в реализацию защиты Web-служб с использованием LTPA-маркеров в WebSphere Application Server V6.
-
"Руководство по Web-сервисам для WebSphere Application Server Version 6.1",
(Проект IBM Redbook, октябрь 2006. Уэли Уоли (Ueli Wahli), Оуэн Барроуз (Owen Burroughs), Оуэн Кляйн (Owen Cline), Алек Гоу (Alec Go), Ларри Танг (Larry Tung)) - полное руководство по разработке и реализации Web-сервисов с использованием WebSphere Application Server V6.1.
-
Полная документация по продукту на сайте WebSphere Application Server V6.1 InfoCenter.
Об авторе  | |  |
Борис Люблинский (Boris Lublinsky) - главный разработчик в CNA Insurance. Он занимается проектированием и реализацией стратегии интеграции CNA, созданием интегрированных прикладных систем и внедрением сервис-ориентированной архитектуры (SOA). Борис имеет более чем двадцатилетний опыт разработки программного обеспечения и технических решений. Вы можете связаться с ним по адресу boris.lublinsky@cna.com. |
Выскажите мнение об этой странице
|  |