|
|
|
Описание для автора не найдено
|
|
|
|
|
|
|
|
Поддержка, обеспечиваемая в расширениях Web-сервисов 2.0 для
спецификации WS-Policy
Автор: Simon Horrell, DevelopMentor
Перевод: Шатохина Надежда(sna@uneta.org), UNETA
(http://www.uneta.org)
Февраль 2004
Применяется к:
Microsoft® ASP.NET
Расширениям Web-сервисов – WSE 2.0
Спецификации WS-Policy
Обзор: : В этой статье описывается
поддержка для WS-Policy в Предварительном представлении технологии WSE 2.0,
приведены доступные возможности политики и показаны примеры их
использования.
Введение
WS-Policy в Расширениях Web-сервисов (WSE) 2.0
Задаем, что в сообщении должен быть маркер доступа
Передача UsernameToken
Передача KerberosToken
Пересылка X509SecurityToken
Задаем, что в сообщении должна быть подпись
Создание подписи с помощью UserNameToken
Создание подписи с помощью маркера доступа X509
Создание подписей с помощью KerberosToken
Установление срока действия сообщения
Задаем, что сообщение должно быть закодировано
Установка безопасного сеанса для обмена многими сообщениями
Использование редактора WSE-политики
Написание и конфигурирование специальных утверждений
Заключение
Введение
Чтобы взаимодействовать с Web-сервисом, необходимо знать его требования,
возможности и предпочтения. Эти политики позволяют приложению выбирать
и использовать Web-сервисы более осмысленно.
Например, приложение, которое хочет взаимодействовать с безопасным
Web-сервисом, должно знать, какую аутентификационную информацию оно должно
представить в сообщении, и должно ли сообщение быть подписанным и/или
закодированным (и как, и какие части). Без этой информации приложение не может
знать наверняка, какой будет связь с этим сервисом.
Эта информация политики должна быть выражена стандартно, чтобы было возможно
взаимодействие между приложениями, разработанными и выполняемыми на
неравноправных платформах. Более того, она должна быть машиночитаемой, чтобы
приложения (или, более вероятно, инфраструктура Web-сервиса) могла создавать код
для реализации политики во время выполнения.
Помня об этом, Microsoft, IBM, BEA и SAP создали Инфраструктуру политики
Web-сервисов (WS-Policy). Она предоставляет модель и расширяемый XML-синтаксис
для описания и связывания политики с Web-сервисом. Более подробно о различных
касающихся политики спецификациях (WS-Policy
(http://msdn.microsoft.com/ws/2002/12/Policy/), WS-PolicyAttachment
(http://msdn.microsoft.com/ws/2002/12/PolicyAttachment/), WS-PolicyAssertions
(http://msdn.microsoft.com/ws/2002/12/PolicyAssertions/), WS-SecurityPolicy
(http://msdn.microsoft.com/ws/2002/12/ws-security-policy/)) и о
их работе смотрите в статье «Понимание WS-Policy
(http://www.uneta.org/Default.aspx?mnuid=E5ED8936-5C6D-4DFD-8A3A-7CDAD3923183&artID=21665A78-D204-4593-92AA-E7607B31607B)»
Аарона Сконнарда.
Недавно Microsoft предоставила поддержку WS-Policy в Расширениях Web-сервисов
(WSE) 2.0 для Microsoft .NET. В этой статье описываются доступные в
Предварительном представлении технологии WSE 2.0 возможности политики и показаны
примеры
(http://download.microsoft.com/download/6/b/f/6bf215e4-79f6-4184-b247-a29341951544/WSE2TP-PolicySample.EXE)
их использования.
WS-Policy в Расширениях Web-сервисов (WSE) 2.0
Расширения Web-сервисов (WSE) 2.0 Microsoft включают частичную реализацию
инфраструктуры WS-Policy, а также предоставляют поддержку нескольким стандартным
утверждениям, детально описанным в спецификации WS–SecurityPolicy, таким как те,
которые требуют наличия маркеров доступа в сообщении, или требуют, чтобы
сообщение было подписано и/или закодировано, или определяют срок действия
сообщения. Они также позволяют поддержку специальных утверждений через
реализацию обработчиков специальных утверждений политики.
В WSE 1.0 не было поддержки WS-Policy, таким образом, создание Web-сервиса,
использующего, например, WS-Security
(http://www.oasis-open.org/committees/download.php/5941/oasis-200401-wss-soap-message-security-1.0.pdf)
для обеспечения безопасности, означало, что вы должны были вручную писать код
для проверки маркеров и подписей для кодирования сообщений и для аутентификации
и авторизации различных пользователей. С WSE 2.0 можно достигнуть тех же
результатов, просто декларативно авторизуя утверждения политики в файле
политики. Инфраструктура WSE 2.0 проверят файл политики и использует утверждения
для реализации политики во время выполнения. Примечание: когда я в этой статье
использую WSE, я имею ввиду Предварительное представление технологии (Technology
Preview) WSE 2.0.
Спецификация WS-PolicyAttachment обозначает, как конкретная политики
ассоциируется с субъектом, к которому она применяется (например, конечной точкой
Web-сервиса). В настоящее время в WSE 2.0 нет поддержки WS-PolicyAttachment,
т.е. назначение политики, также как и самой политики, определяется в файле
политики. Структура файла политики показана ниже.
<policyDocument
xmlns="http://microsoft.com/wse/2003/06/PolicyDocument">
<mappings>
<map to="http://www.develop.com/someapp/someservice.asmx">
<action
name="http://www.develop.com/someapp/someservice/someop"
policy="#policy1"/>
</map>
<map to="http://www.develop.com/someapp/someotherservice.asmx">
<default policy="#policy2"/>
</map>
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:Policy wsu:Id="policy1">
<!-- Здесь располагаются утверждения политики -->
...
</wsp:Policy>
<wsp:Policy wsu:Id="policy2">
<!-- Здесь располагаются утверждения политики -->
...
</wsp:Policy>
</policies>
</policyDocument>
Корневой элемент файла политики — policyDocument из
пространства имен
http://microsoft.com/wse/2003/06/PolicyDocument. Элемент
policyDocument включает элемент policies, в
который входят один или более элементов Policy, каждый из
которых содержит описание политики и его утверждения политики. Поддерживаемые
WSE 2.0 утверждения политики — основной предмет рассмотрения этой статьи и будут
изучены позднее. В элемент policyDocument также входит элемент
mappings, который содержит один или более элементов
map. Каждый элемент map связывает операции
конечной точки, определенную его атрибутом to, с политикой,
которая будет на самом деле применяться для операций. Элемент
action определяет, какой Web-метод в отдельной конечной точке
Web-сервиса для какой политики применяется. Он задает (через атрибут
name), что ассоциированная политика применяется к сообщениям с
определенным «действием» — элемент action, определенный
WS-Addressing (который будет преобразован в HTTP-заголовок
SOAPAction для SOAP через HTTP). Обратите внимание, что
Web-сервисы ASMX используют HTTP-заголовок SOAPAction для
определения того, какому Web-методу в рамках отдельной конечной точки
Web-сервиса предназначается запрос. Элемент default
устанавливает, что политика применяется к сообщениям, для которых не было задано
соответствующего элемента action. Если элемент
default не определен для конечной точки, любые сообщения,
отправленные в эту конечную точку и содержащие элемент action,
который не задан в политике, автоматически дадут сбой. Атрибут
policy, как в элементе action, так и в
элементе default, называют политику. В этом случае операция,
идентифицированная
http://www.develop.com/someapp/someservice/someop в конечной
точке http://www.develop.com/someapp/someservice.asmx,
преобразовывается в политику с ID #policy1, а все операции в
конечной точке
http://www.develop.com/someapp/someotherservice.asmx
преобразовываются в политику с ID #policy2.
Вы должны указать WSE, где находятся файл(ы) политики, применяемые к
приложению. Вы делаете это в конфигурационном файле приложения; для приложений
Microsoft ASP.NET это будет Web.config, а для исполняемых файлов .NET —
Assemblyname.exe.config. пример файла конфигурации приведен здесь. Примечание:
разрывы строк в значениях атрибутов (здесь, в частности, атрибута
type) сделаны только в целях обеспечения ясности отображения.
Настоящие файлы конфигурации не должны иметь разрывов строк в значениях
атрибутов.
<configuration>
<!-- Надо конфигурировать обработчик секции для microsoft.web.services -->
<configSections>
<section
name="microsoft.web.services"
type="Microsoft.Web.Services.Configuration.WebServicesConfiguration,
Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
<system.web>
<webServices>
<!-- WSE 2.0 конфигурирован как расширение SOAP -->
<soapExtensionTypes>
<add
type="Microsoft.Web.Services.WebServicesExtension,
Microsoft.Web.Services, Version=2.0.0.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35"
priority="1"
group="0" />
</soapExtensionTypes>
</webServices>
</system.web>
<microsoft.web.services>
<policy>
<receive>
<cache name="rpolicies.xml" />
</receive>
<send>
<cache name="spolicies.xml" />
</send>
</policy>
</microsoft.web.services>
</configuration>
Обратите внимание, как WSE 2.0 была конфигурирована как SOAP-расширение для
приложения, и как секция конфигурации microsoft.web.services
должна быть конфигурирована перед тем, как может быть использован элемент
конфигурации microsoft.web.services. Также заметьте, что WSE
разделяет политики «отправки» и политики «получения».
Политика получения выполняется при поступлении сообщений. Если полученное
сообщение не соответствует политике получения, тогда WSE генерирует SOAP-ошибку
и возвращает ее отправителю без выполнения целевой операции. Например, если
политика получения определяет, что тело сообщения должно быть подписано, а оно
не подписано, тогда сообщение не будет принято.
Политика отправления проверяет сообщения на соответствие политике прямо перед
их отправкой. Если сообщение не удовлетворяет политике, тогда WSE может изменить
его, чтобы достигнуть соответствия. Например, политика отправления может
утверждать, что тело исходящего сообщения должно быть закодировано. если к
отправке готовится сообщение с незакодированным телом, инфраструктура попытается
перед отправкой закодировать его, в соответствие с требованиями политики.
Разделение политики получения и политики отправления конечно же имеет смысл,
поскольку условия, предъявляемые к отправке и получению сообщений, часто сильно
отличаются. Зачастую приложению надо будет определить или только политику
отправления, или только политику получения, а не обе сразу.
Единственное, чего не касается инфраструктура WS-Policy — то, как
обнаруживать политики. Чтобы заранее определить, могут ли они общаться друг с
другом, клиенту и Web-сервису сначала надо будет вступить, в некотором роде, в
переговоры о политике.
Теперь пришло время рассмотреть несколько характерных примеров того, как WSE
2.0 поддерживает некоторые стандартные утверждения, определенные в спецификации
WS-SecurityPolicy.
Задаем, что в сообщении должен быть маркер доступа
Утверждение SecurityToken, определенное в спецификации
WS-SecurityPolicy, требует, чтобы в сообщении находился какой-нибудь маркер
доступа (например, сертификат X.509), который представляет отправителя,
например, указывает, кто такой отправитель. Формат утверждения
SecurityToken показан ниже.
<wsee:SecurityToken
wsp:Usage="..."
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:TokenType>...</wsse:TokenType>
<wsse:TokenIssuer>...</wsse:TokenIssuer>
<wsse:Claims>...</wsse:Claims>
<!-- Информация, касающаяся типа маркера -->
</wsse:SecurityToken>
На данный момент WSE 2.0 поддерживает четыре широко известных типа маркеров,
как показано ниже, а также специальные типы маркеров.
Qname |
Описание |
wsse:X509v3 |
Сертификат X.509 v3 |
wsse:Kerberosv5ST |
Мандат сервиса Kerberos V5 |
wsse:UsernameToken |
Маркер имени пользователя, определенный в WS-Security |
wsse:SecurityContextToken |
SecurityContextToken, определенный в
WS-SecureConversation |
Таблица 1. Поддерживаемые типы маркеров
Передача UsernameToken
Вероятно, начать надо с самого простого и универсального маркера доступа —
UsernameToken, который обеспечивает возможность задать имя
пользователя и пароль (не обязательно). Здесь представлена политика, которая
определяет, что в сообщении должен быть UsernameToken.
<policyDocument
xmlns="http://microsoft.com/wse/2003/06/PolicyDocument">
<mappings>
<map to="http://localhost/policyapp/secureservice.asmx">
<!-- Соответствует операции PassToken -->
<action
name="http://develop.com/policyapp/secureservice/passtoken"
policy="#PresentAUserNameToken"/>
</map>
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:Policy wsu:Id="PresentAUserNameToken">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>UsernameToken</TokenType>
</SecurityToken>
</wsp:Policy>
</policies>
</policyDocument>
Это, как и все приведенные в этой статье политики — политика отправления
клиента Web-сервиса и политика получения Web-сервиса. Обратите внимание, что для
UsernameToken не должно быть элемента
TokenIssuer.
Чтобы реализовать утверждение политики от лица клиента Web-сервиса, знающее
его WSE должно отправить сообщение, которое содержит
UsernameToken, но оно не знает, какой
именноUserNameToken. Чтобы получить эту информацию, WSE
просматривает кэш маркеров, представленный классом
Microsoft.Web.Services.Security.SecurityTokenCache.
В данном случае клиент Web-сервиса отвечает за заполнение
SecurityTokenCache определенным UsernameToken
до того, как сделает вызов к прокси Web-сервиса, как показано ниже.
SecureServiceWse s = new SecureServiceWse();
UsernameToken tok =
new UsernameToken(
"LAP-SIMON\simonh",
"notreallymypwd",
PasswordOption.SendPlainText);
SecurityTokenCache.GlobalCache.Add(tok);
s.PassToken(); // Операция, к которой применяется политика
Получатель сообщения, естественно, захочет аутентифицировать маркер доступа и
затем использовать содержащуюся в нем информацию для авторизации того, что
позволено или не позволено владельцу этого маркера. Такая авторизация может
основываться на том, кто является владельцем маркера или членом каких
функциональных ролей он является.
Когда WSE получает сообщение, содержащее UsernameToken, чей
пароль был послан незашифрованным, оно автоматически пытается аутентифицировать
удостоверения UsernameToken в отношении к учетной записи
Windows®. Если это удается, тогда роли приравнивают к группам Windows NT®, и
ролевая принадлежность аутентифицированного пользователя определяется его
принадлежностью к группе Windows NT.
Однако не стоит ожидать, что пароли будут посылаться незакодированными. В
предыдущей политике никаких особых требований к UsernameToken
не было предъявлено — даже то, что должен пересылаться пароль. Приведенная ниже
политика, однако, утверждает, что должен присутствовать безопасный хэш
пароля.
<wsp:Policy wsu:Id=" PresentAUserNameToken2"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>UsernameToken</TokenType>
<Claims>
<UsePassword wsp:Usage="wsp:Required"
Type="wsse:PasswordDigest"/>
</Claims>
</SecurityToken>
</wsp:Policy>
Стандартное значение атрибута Type, если он не задан —
wsse:PasswordText (простой текстовый пароль).
В этом случае код клиента немного изменится.
SecureServiceWse s = new SecureServiceWse();
UsernameToken tok =
new UsernameToken(
"LAP-SIMON\simonh",
"notreallymypwd",
PasswordOption.SendHashed);
SecurityTokenCache.GlobalCache.Add(tok);
s.PassToken();
Тем не менее, помните, что теперь WSE не может преобразовывать
UsernameToken в учетную запись Windows, потому что нет простого
текстового пароля.
Если такое происходит, или если удостоверения, содержащиеся в
UsernameToken, не преобразовываются в учетную запись Windows,
тогда Web-сервис может самостоятельно аутентифицировать входящие
UsernameTokens, предоставляя реализацию диспетчера маркера.
Затем он может преобразовать удостоверения в Principal любым
способом, каким только захочет, используя специальную реализацию
UsernameTokenManager, как показано ниже.
public class MySecurityTokenManager : UsernameTokenManager {
protected override string AuthenticateToken(UsernameToken token) {
string pwd;
switch(token.Username) {
case "Simon":
pwd = token.Username+"-pwd";
token.Principal = new GenericPrincipal(
new GenericIdentity(token.Username),
new string[] {"SomeRole","SomeOtherRole"} );
break;
case "Guest":
pwd = token.Username+"-pwd";
token.Principal = new GenericPrincipal(
new GenericIdentity(token.Username),
new string[] {"SomeRole"} );
break;
default:
pwd = base.AuthenticateToken(token);
break;
}
return pwd;
}
}
Заметьте, как диспетчер создает собственный Principal на
базе имени пользователя из предоставленного UsernameToken, но с
ролевой принадлежностью. Затем он присваивает его свойству
Principal в UsernameToken.
Диспетчер маркера должен быть зарегистрирован в файле Web.config Web-сервиса,
как показано здесь.
<configuration>
...
<microsoft.web.services>
...
<security>
...
<securityTokenManager
qname="wsse:UsernameToken"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext"
type="policyapp.MySecurityTokenManager, policyapp" />
</security>
</microsoft.web.services>
</configuration>
Независимо от того, аутентифицирован UsernameToken с
использованием учетной записи Windows или с использованием специальной техники
аутентификации, результат этой аутентификации доступен цели сообщения. Следующий
пример иллюстрирует, как использовать эту информацию для проведения авторизации
в рамках, скажем, реализации метода Web-сервиса.
Principal p =
RequestSoapContext.Current.Security.Tokens[0].Principal;
if (p!=null && p.Identity.Name=="LAP-SIMON\simonh")
{
// чего-то делаем
}
Однако, если Web-сервис заинтересован только в предоставлении или не
предоставлении доступа к конкретной операции на основании результата
аутентификации, тогда это может быть выражено декларативно, как показано здесь,
вообще без необходимости добавления какого-либо кода в метод Web-сервиса.
<policyDocument
xmlns="http://microsoft.com/wse/2003/06/PolicyDocument">
<mappings>
<map to="http://localhost/policyapp/secureservice.asmx">
<action
name="http://develop.com/policyapp/secureservice/passtoken"
policy="#PresentAUserNameToken"/>
</map>
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:Policy wsu:Id="PresentAUserNameToken">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>UsernameToken</TokenType>
<Claims>
<SubjectName
MatchType="wsse:Exact">LAP-SIMON\simonh</SubjectName>
</Claims>
</SecurityToken>
</wsp:Policy>
</policies>
</policyDocument>
Обратите внимание, что в этом случае элемент Claims
определяет точно соответствие для имени пользователя. В этом случае только
пользователю LAP-SIMON\simonh позволено вызывать Web-метод. Атрибут
MatchType может иметь значение wsse:Exact
(точное соответствие), wsse:Regexp (соответствие регулярному
выражению) или wsse:Prefix (соответствие префиксов),
применяемое по умолчанию.
Скорее всего доступ к операции должен быть детерминирован не только
пользователем, ассоциированным с маркером, но и ролевой принадлежностью
пользователя. Создатель метода может написать код для этого.
Principal p =
RequestSoapContext.Current.Security.Tokens[0].Principal;
if (p!=null &&
(p.IsInRole("LAP-SIMON\SomeRole")||
p.IsInRole("LAP-SIMON\SomeOtherRole"))
{
// чего-то делаем
}
Однако этот тип доступа к методу, основывающийся на ролевой принадлежности,
также можно декларативно конфигурировать в политике. Приведенная ниже политика
показывает, как ограничить доступ к Web-методу для членов или LAP-SIMON\SomeRole
роли, или LAP-SIMON\SomeOtherRole роли.
<wsp:Policy wsu:Id="PresentAUserNameToken2"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>UsernameToken</TokenType>
<Claims>
<wse:Role value="LAP-SIMON\SomeRole"/>
<wse:Role value="LAP-SIMON\SomeOtherRole"/>
</Claims>
</SecurityToken>
</wsp:Policy>
UsernameToken довольно прост в использовании и универсально
подходит для большинства сценариев обеспечения безопасности на большинстве
платформ, но есть и проблемы. Паролями трудно управлять и в случае, когда пароль
хэширован (то, чего вы обычно хотите), было показано, что WSE не может
автоматически преобразовать UsernameToken в учетную запись
Windows. В случаях, когда вы знаете, что удостоверения клиента вашего
Web-сервиса будут преобразованы в учетную запись Windows на сервере,
предоставляющем хостинг Web-сервису, но вы не хотите посылать пароли
незакодированными, тогда вам, вероятно, захочется использовать
KerberosToken.
Передача KerberosToken
Если WSE 2.0 установлен на Windows Server™ 2003 или Windows® XP с Service
Pack 1, тогда он имеет поддержку для Kerberos-аутентификации в форме
KerberosToken. Преимущество Kerberos в том, что он является
открытым стандартом безопасности, таким образом, способствуя возможности
взаимодействовать между WSE-приложениями Web-сервисов, выполняемыми в Windows, и
приложениями Web-сервисов, выполняемыми не на Windows-платформах.
Приведенная ниже политика показывает, как конфигурировать работу Web-сервиса,
чтобы принимать в качестве маркеров доступа мандат Kerberos.
<wsp:Policy wsu:Id="PassKerberosToken"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>Kerberosv5ST</TokenType>
</SecurityToken>
</wsp:Policy>
И опять же, в этом случае, поскольку точные детали конкретного мандата
Kerberos не были определены, клиент Web-сервиса должен поместить в
SecurityTokenCache определенный маркер — на этот раз
KerberosToken — перед тем, как вызывать прокси Web-сервиса, как
показано здесь.
string name = "host/" + System.Net.Dns.GetHostName();
KerberosToken tok = new KerberosToken(name);
SecurityTokenCache.GlobalCache.Add(tok);
s.PassToken();
KerberosToken создается из безопасного содержимого текущего
пользователя Windows — его свойство Principal автоматически
устанавливается на этого пользователя — таким образом, он содержит мандат
Kerberos, который позволяет клиенту Web-сервиса (работающему от имени текущего
пользователя) обмениваться информацией с указанным хостом (в данном случае, той
же машиной).
Политика, подробно описывающая, какой конкретный мандат Kerberos
использовать, показана ниже.
<wsp:Policy wsu:Id="PassKerberosToken"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>Kerberosv5ST</TokenType>
<TokenIssuer>DM</TokenIssuer>
<Claims>
<SubjectName>DM\simonh</SubjectName>
<ServiceName>host/LAP-SIMON</ServiceName>
</Claims>
</SecurityToken>
</wsp:Policy>
В данном случае, все что надо сделать клиенту Web-сервиса — вызвать метод
Web-сервиса, поскольку у WSE есть вся необходимая информация для получения
мандата Kerberos и представления его как KerberosToken.
Как показано выше, когда WSE получает сообщение, он автоматически
преобразовывает мандат Kerberos в учетную запись пользователя Windows.
Однако, если хостинг, или клиент Web-сервиса, или Web-сервис — не
поддерживает Kerberos, тогда возвращаемся к тому, с чего начали. Конечно,
замечательно передавать информацию об имени пользователя/пароле от клиента к
серверу, но если клиент захочет проверить достоверность сообщения, отправленного
с сервера, тогда нет гарантии, что все сработает хорошо. Во избежание этой
проблемы, в качестве средств передачи удостоверений можно выбрать сертификаты
X.509.
Пересылка X509SecurityToken
WSE 2.0 поддерживает сертификаты X.509 в форме
X509SecurityToken. В то время как отдельные пользователи часто
не имеют собственных сертификатов, организации их имеют. Поэтому такой режим
работы лучше подходит для ситуаций, в которых клиент хочет знать сервер, или в
сценариях business-to-business и интеграции прикладных систем предприятия,
вовлекающих меж- и внутриорганизационную связь.
Эта политика показывает, как конфигурировать работу Web-сервиса, чтобы он в
качестве маркера доступа принимал сертификат X.509.
<wsp:Policy wsu:Id="PassX509CertificateToken"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<SecurityToken wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenType>X509v3</TokenType>
<Claims>
<SubjectName>CN=WSE2QuickStartClient</SubjectName>
</Claims>
</SecurityToken>
</wsp:Policy>
В этом случае принимается только сообщение, содержащее маркер, представляющий
сертификат с общепринятым именем WSE2QuickStartClient.
Нет необходимости клиенту добавлять необходимый
X509SecurityToken в SecurityTokenCache, потому
что WSE знает имя сертификата из элемента Claims и, таким
образом, может загрузить его из хранилища сертификатов самостоятельно. Т.е.
клиент становится даже еще более простым, чем раньше, как показано здесь.
SecureServiceWse s = new SecureServiceWse();
s.PassToken();
Конечно же, если приведенная выше политика не учитывает элемент
Claims, что означает, что может быть представлен любой
сертификат, тогда клиенту придется вручную создавать
X509SecurityToken из сертификата, загруженного из
соответствующего хранилища сертификатов, и добавлять его в
SecurityTokenCache во время выполнения.
Перед тем как продолжить, возможно, полезно понять, как извлечь и установить
сертификаты, необходимые для самостоятельного тестирования примеров.
Первый шаг — получение сертификата. Вы можете создать сертификат
самостоятельно, используя утилиту makecert, например. В
качестве альтернативы, вы можете создать запрос на сертификат и отправить его в
центр выдачи сертификатов, такой как Verisign, который тогда выпустить
сертификат. Сервисы по присвоению сертификатов Microsoft® позволят вам создать
запрос на сертификат и выпустить его для локализованного использования. И
наконец, вы можете использовать существующий сертификат. Примеры WSE 2.0
поступают вместе с двумя простыми сертификатами, подписанными «Root agency» для
целей тестирования: один для использования клиентом Web-сервиса (общепринятое
имя — WSE2QuickStartClient) и один для использования
Web-сервисом (общепринятое имя — WSE2QuickStartServer). Все
связанные с использованием сертификатов примеры в этой статье используют эти
сертификаты. Обратите внимание, что в документации WSE 2 Readme есть
предупреждение о проблемах производительности, возникающих при использовании
этих пробных сертификатов. Оно выглядит так:
«Определенные безопасные операции могут приводить к уменьшению
производительности при использовании сгенерированных makecert сертификатов.
Сертификаты, выпущенные реальным Центром выдачи сертификатов не имеют таких
проблем. Это известная проблема предварительного технического
представления.»
Второй шаг — помещение сертификата или в хранилище сертификатов «CurrentUser»
(представляющем зарегистрированного на данный момент пользователя), или в
хранилище сертификатов «LocalMachine». Это можно сделать, выполняя модульный
компонент MMC Certificates. Сертификаты, включая любой из сертификатов в цепочке
сертификатов организации, их выпускающего, которые необходимы коду, выполняемому
под видом имеющей права регистрации учетной записи, обычно отправляются в
хранилище «CurrentUser». Сертификаты, необходимые коду, который выполняется как
учетная запись без прав регистрации, включая любой из сертификатов в цепочке
сертификатов организации, их выпускающего, обычно помещаются в хранилище
«LocalMachine». В примерах WSE 2.0 есть инструкции установки
сертификатов-образцов. Это файл .pfx (содержащий секретный и открытый ключи) для
сервера, который устанавливается в хранилище сертификатов «LocalMachine», и файл
.pfx для клиента, который устанавливается в хранилище сертификатов
«CurrentUser». Также есть файл .cer (содержащий только открытый ключ) для
сервера, который устанавливается в хранилище сертификатов «CurrentUser». Все
касающиеся сертификатов примеры в этой статье предполагают эту установку.
Как упоминалось ранее, иногда вашему коду может понадобится выбрать, какие
сертификаты ему нужны во время выполнения, и загрузить их программно из
соответствующего хранилища сертификатов. Однако иногда необходимые сертификаты
определены в декларативном файле политики (как в предыдущей показанной политике)
и загружаются WSE от вашего имени. Для этого WSE надо будет знать, какой из
хранящихся сертификатов использовать. По умолчанию WSE использует хранилище
«LocalMachine», что особенно важно для Web-сервиса, когда он выполняется под
учетной записью системы безопасности, у которой нет прав регистрации (например,
учетная запись рабочего процесса ASP.NET). однако, чтобы заставить предыдущий
пример работать, клиенту Web-сервиса надо, чтобы WSE получил сертификат
WSE2QuickStartClient из хранилища «CurrentUser». В этом случае
его файл конфигурации должен выглядеть так:
<configuration>
...
<microsoft.web.services>
...
<security>
...
<x509 storeLocation="CurrentUser" />
</security>
</microsoft.web.services>
</configuration>
Получатель сообщения, в котором есть сертификат, должен проверить, может ли
он доверять информации, содержащейся в сертификате. Перед тем, как сертификату
можно доверять, надо проверить последовательность его сертификации, чтобы
удостовериться, что он восходит к пользующемуся доверием корневому органу выдачи
сертификатов. После это надо провести проверку, подтверждающую, что сертификат
не был аннулирован. Атрибуты элемента X509, показанного выше в
файле конфигурации, полезны с этой точки зрения, поскольку они помогают WSE в
проведении проверки достоверности сертификата.
Атрибут |
Описание |
storeLocation |
Определяет, из какого хранилища сертификатов WSE извлекает сертификаты
X.509 при проверке достоверности. Стандартным является хранилище
«LocalMachine». |
verifyTrust |
Определяет, проводить ли WSE проверки того, что последовательность
сертификатов выпускающего их органа простирается до пользующегося доверием
корневого органа выдачи сертификатов или нет. Значение по умолчанию —
true. |
allowTestRoot |
Определяет, изменять ли WSE процесс проверки достоверности, чтобы
позволить сертификатам X.509, подписанным корневым каталогом тестирования,
проходить эту проверку, или нет. Значение по умолчанию — false. |
allowRevocationUrlRetrieval |
Определяет, определять ли WSE URLы во время проверки аннулирования
сертификата, или нет. Когда его значение «false», используются только
кэшированные URLы. Значение по умолчанию — true. |
allowUrlRetrieval |
Определяет, определять ли WSE URLы во время проверки цепочки
сертификатов выпускающего их органа, или нет. Когда его значение «false»,
используются только кэшированные URLы. Значение по умолчанию —
false. |
Таблица 2. Атрибуты
У образцов сертификатов, поступающих вместе с примерами кода WSE, нет цепочки
сертификатов выпускающего их органа, который простирается до корневого органа
выдачи сертификатов — они подписаны тестовым «Root agency». Единственный способ
заставить последний пример работать — изменить файл Web.config Web-сервииса так,
чтобы он выглядел, как показанный ниже.
<configuration>
...
<microsoft.web.services>
...
<security>
<x509 allowTestRoot="true" />
</security>
</microsoft.web.services>
</configuration>
В настоящее время WSE не поддерживает автоматическое преобразование
сертификатов X.509 в учетные записи пользователя Windows, хотя вы можете
написать код, преобразовывающий сертификаты в ваше собственное хранилище
удостоверений Windows, и вставить его в систему аутентификации X.509.
Задаем, что в сообщении должна быть подпись
Просто пересылка маркера доступа как части сообщения не имеет большого
значения; отправить ее мог кто угодно. Получателю сообщения нужно доказательство
того, что сообщение было действительно отправлено владельцем маркера, т.е.
доказательство того, что отправитель сообщения заложил достоверную гарантию в
удостоверения, посланные в маркере. Этого можно достигнуть, применяя цифровые
подписи для всего или для частей сообщения, создаваемые с помощью некоторого
известного только владельцу маркера «секретного ключа», ассоциированного с
маркером доступа. Это может быть и распределенный секрет (например, пароль) или,
возможно, секретный ключ. Если получатель может проверить достоверность подписи,
используя или распределенный секрет, или соответствующий открытый ключ, тогда он
демонстрирует, что отправитель сумел продемонстрировать информацию или нечто,
ассоциированное с маркером, которую мог знать только отправитель.
Однако даже если получатель наверняка знает происхождение подписанных частей
сообщения, кто угодно мог пытаться подделать сообщение во время пересылки.
Подпись некоторых данных формируется не из самих данных, а из дайджеста (то же
самое, что хэш) данных. Если получатель при проверке достоверности подписи
проводит такое же хэширование и получает аналогичный дайджест, тогда получатель
знает, что сообщение не был изменено с момент его подписания. Таким образом,
подпись обеспечивает доказательство того, что подписанные части сообщения на
самом деле поступили от подразумеваемого отправителя и не изменялись с момента
отправки.
Правильно разработав политику, вы можете заставить WSE подписывать сообщения
перед их отправкой и проверять достоверность при их получении. Утверждение
Integrity, определенное в спецификации WS-SecurityPolicy,
используется для обозначения требуемого формата подписи, как сказано в
спецификации WS-Security. Структура утверждения Integrity
показана ниже.
<wsse:Integrity
wsp:Preference="..."
wsp:Usage="..."
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<wsse:Algorithm Type="..." URI="..." wsp:Preference="..."/>
<wsse:TokenInfo>
<wsse:SecurityToken>...</wsse:SecurityToken>
</wsse:TokenInfo>
<wsse:Claims>...</wsse:Claims>
<wsse:MessageParts Dialect="..." Signer="...">
...
</wsse:MessageParts>
<wsse:Integrity>
Маркеры WSE, поддерживающие подписи: UsernameToken,
X509SecurityToken, KerberosToken,
SecurityContextToken, DerivedKeyToken и
специальные маркеры.
Создание подписи с помощью UserNameToken
Следующий файл политики показывает, как задать, чтобы любой
UsernameToken должен подписывать сообщение.
<policyDocument
xmlns="http://microsoft.com/wse/2003/06/PolicyDocument">
<mappings>
<map to="http://localhost/policyapp/secureservice.asmx">
<action
name="http://develop.com/policyapp/secureservice/signwithtoken"
policy="#SignBodyWithUserNameToken"/>
</map>
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:Policy wsu:Id="SignBodyWithUserNameToken">
<Integrity wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenInfo>
<SecurityToken wsp:Usage="wsp:Required">
<TokenType>UsernameToken</TokenType>
</SecurityToken>
</TokenInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
</Integrity>
</wsp:Policy>
</policies>
</policyDocument>
В этом случае пароль пользователя используется для подписания и проверки
достоверности сообщения.
Элемент MessageParts описывает, какие части сообщения должны
быть подписаны. Если вы хотите подписать сообщение программно с помощью WSE, не
уточняя, какие части хотите подписать, по умолчанию будут подписаны следующие
части сообщения:
soap:Envelope/soap:Header/soap:Body
soap:Envelope/soap:Header/wsu:Timestamp/wsu:Created
soap:Envelope/soap:Header/wsu:Timestamp/wsu:Expires
soap:Envelope/soap:Header/wsa:Action,
soap:Envelope/soap:Header/wsa:To
soap:Envelope/soap:Header/wsa:MessageID
soap:Envelope/soap:Header/wsa:From/wsa:Address
Конечно же, можно не полагаться на эти стандарты и программно точно
определять, какие части сообщения вы хотите подписать. При декларативном
определении того, что сообщение должно быть подписано, WSE утверждает, что
должен присутствовать элемент MessageParts для указания на то,
какие части сообщения должны быть подписаны. Элемент
MessageParts для описания частей сообщения использует диалект.
В спецификации WS-PolicyAssertions описаны два диалекта. Диалект
http://www.w3.org/TR/1999/REC-xpath-19991116 означает, что для
описания частей сообщения должны использоваться выражения XPath. Кроме того, он
определяет набор функций для упрощения выражений, которые могут использоваться
для ссылки на элементы SOAP-сообщения. Хотя этот диалект предложен спецификацией
как стандартный, он не поддерживается WSE. Другой диалект
http://schemas.xmlsoap.org/2002/12/wsse#part определяет функции
для идентификации частей сообщения. Поддерживаемые функции показаны ниже.
Функция |
Описание |
wsp:Body() |
Эта функция определяет «тело» сообщения. |
wsp:Header(x) |
Эта функция определяет «заголовок», именем которого является заданное
QName, x. |
Таблица 3. Поддерживаемые функции
Как видите, приведенная выше политика утверждает, что тело
(soap:Envelope/soap:Header/soap:Body) сообщения должно быть
подписано. Подписать несколько частей сообщения можно или имея один элемент
MessageParts, чье содержимое — список функций, разделенных
пробелами, или имея множество элементов MessageParts. В
соответствие со следующей политикой, должны быть подписаны тело и заголовок
soap:Envelope/soap:Header/wsa:Action сообщения.
<wsp:Policy wsu:Id="SignBodyAndHeaderWithUserNameToken"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<Integrity wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenInfo>
<SecurityToken wsp:Usage="wsp:Required">
<TokenType>UsernameToken</TokenType>
</SecurityToken>
</TokenInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
<MessageParts
xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing"
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Header(wsa:Action)
</MessageParts>
</Integrity>
</wsp:Policy>
Обратите внимание, что в текущей реализации WSE использовать утверждение
Integrity, можно только используя следующие части сообщения в
диалекте http://schemas.xmlsoap.org/2002/12/wsse#part:
wsp:Body() или wsp:Header() для заголовков
спецификации WS-Addressing To, Action,
From, ReplyTo, RelatesTo,
Recipient, FaultTo и
MessageID.
Клиент и код Web-сервиса, к которому будет применяться одна из двух ранее
рассмотренных политик, не сильно изменяться по сравнению с предыдущим вариантом,
поскольку WSE будет автоматически добавлять подпись в сообщение во время его
отправки и проверять подпись при получении сообщения. Код клиента показан
ниже.
SecureServiceWse s = new SecureServiceWse();
UsernameToken tok =
new UsernameToken(
"LAP-SIMON\simonh",
"notreallymypwd",
PasswordOption.SendHashed);
SecurityTokenCache.GlobalCache.Add(tok);
s.SignWithToken();
Создание подписи с помощью маркера доступа X509
Если применяется приведенная ниже политика, тогда для подписания тела и
заголовка soap:Envelope/soap:Header/wsa:Action сообщения будет
использоваться сертификат X.509.
<wsp:Policy wsu:Id="SignBodyAndHeaderWithX509CertificateToken"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<Integrity wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenInfo>
<SecurityToken>
<TokenType>X509v3</TokenType>
<Claims>
<SubjectName>CN=WSE2QuickStartClient</SubjectName>
</Claims>
</SecurityToken>
</TokenInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part"
xmlns:wsa="http://schemas.xmlsoap.org/ws/2003/03/addressing">
wsp:Body() wsp:Header(wsa:Action)
</MessageParts>
</Integrity>
</wsp:Policy>
Для подписания сообщения используется секретный ключ сертификата, и для
проверки достоверности сообщения — открытый ключ сертификата.
В данном случае клиенту Web-сервиса или Web-сервису, на самом деле, нечего
делать, поскольку WSE будет автоматически добавлять подпись в сообщение при его
отправке и проверять достоверность сообщения при его получении. Все, что надо
сделать клиенту — вызвать метод, как показано здесь.
SecureServiceWse s = new SecureServiceWse();
s.SignWithToken();
Создание подписей с помощью KerberosToken
Приведенная ниже политика требует, чтобы тело сообщения было пописано
KerberosToken.
<wsp:Policy wsu:Id="SignBodyWithKerberosToken"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<Integrity wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenInfo>
<SecurityToken wsp:Usage="wsp:Required">
<TokenType>Kerberosv5ST</TokenType>
</SecurityToken>
</TokenInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
</Integrity>
</wsp:Policy>
В этом случае сообщение подписывается и проверяется с помощью секретного
ключа, находящегося в мандате Kerberos, который ассоциирован с
KerberosToken.
Установление срока действия сообщения
Даже когда сообщения подписаны, все еще существует вероятность их повторной
отправки Web-сервису, что может иметь нежелательный эффект. Чтобы минимизировать
эту возможность, можно создать политику, определяющую срок действия сообщения. В
этом случае WSE будет отправлять сообщения с Timestamp со
сроком действия, равным утвержденному политикой MessageAge.
Использование утверждения политики MessageAge показано в файле
политики, приведенном здесь.
<wsp:Policy wsu:Id="AgeMessage"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<MessageAge
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext"
wsp:Usage="required"
Age="60" />
</wsp:Policy>
Любое полученное WSE сообщение с истекшим сроком действия не будет принято. И
никакого написания дополнительного кода в клиенте Web-сервиса или Web-сервисе
вообще не требуется.
Конечно, важно задать атрибуту Age утверждения
MessageAge значение (в секундах), достаточно большое, чтобы
сообщение могло быть обработано при нормальных условиях, но и было защищено от
атак с повторением пакетов. Нелишним будет также подписать заголовок
Timestamp, чтобы предотвратить его от подделки. Из-за
упомянутых ранее ограничений, на данный момент невозможно с помощью WSE
подписать заголовок Timestamp на основании выражения политики,
поэтому это должно быть сделано программно.
Задаем, что сообщение должно быть закодировано
Когда к SOAP-сообщению применяется подпись, она гарантирует, что отправитель
не может отказаться от сообщения, и то, что целостность сохранена. Однако само
сообщение пересылается открытым текстом. Если необходимо, чтобы сообщение или
его части были конфиденциальны для отправителя и получателя, тогда сообщение
должно быть закодировано.
WSE позволяет декларативное описание требований кодирования, из условия что
WSE будет кодировать сообщения перед их отправкой и будет декодировать их при
получении. Утверждение Confidentiality, определенное в
спецификации WS-SecurityPolicy, используется, чтобы показать требуемый формат
кодирования, определенный в спецификации WS-Security. Формат утверждения
Confidentiality проиллюстрирован ниже.
<Confidentiality
wsp:Preference="..."
wsp:Usage="..."
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy"
xmlns:wsse="http://schemas.xmlsoap.org/ws/2002/12/secext">
<Algorithm Type="..." URI="..." wsp:Preference="..."/>
<KeyInfo>
<SecurityToken .../>
<SecurityTokenReference .../>
...
</KeyInfo>
<MessageParts Dialect="...">
...
</MessageParts>
</Confidentiality>
Маркеры WSE, поддерживающие кодирование: X509SecurityToken,
KerberosToken, SecurityContextToken,
DerivedKeyToken и специальные маркеры. Приведенная ниже
политика показывает, как задать то, что X509SecurityToken
должен закодировать тело сообщения.
<policyDocument
xmlns="http://microsoft.com/wse/2003/06/PolicyDocument">
<mappings>
<map to="http://localhost/policyapp/secureservice.asmx">
<action
name="http://develop.com/policyapp/secureservice/encryptwithtoken"
policy="#EncryptBodyWithX509CertificateToken"/>
</map>
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:Policy wsu:Id="EncryptBodyWithX509CertificateToken">
<Confidentiality wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<KeyInfo>
<SecurityToken wsp:Usage="wsp:Required">
<TokenType>X509v3</TokenType>
<Claims>
<SubjectName>CN=WSE2QuickStartServer</SubjectName>
</Claims>
</SecurityToken>
</KeyInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
</Confidentiality>
</wsp:Policy>
</policies>
</policyDocument>
Чем кодировать данные непосредственно с помощью открытого ключа сертификата,
лучше кодировать данные общим ключом, который закодирован открытым ключом
сертификата и включен в сообщение. Секретный ключ сертификата используется для
декодирования общего ключа, который затем используется для декодирования данных.
Использование симметричного ключа для кодирования/декодирования всех данных
намного ускоряет этот процесс, чем использование ассиметричных ключей.
И опять же, клиенту Web-сервиса и Web-сервису ничего не надо делать,
поскольку WSE автоматически закодирует сообщение перед отправкой и декодирует
его при получении. В этом случае все, что должен сделать клиент — вызвать метод,
как показано здесь.
SecureServiceWse s = new SecureServiceWse();
s.EncryptWithToken();
WSE должен иметь разрешение на получение секретного ключа из локального
хранилища компьютера, чтобы иметь возможность осуществить декодирование общего
ключа. Это означает или запуск ASP.NET под учетной записью, имеющей необходимые
полномочия (System или владелец ключа), или предоставление учетной записи
ASP.NET с необходимыми полномочиями. Последнее можно сделать следующим
образом.
- Открыть инструмент WseCertificate.
- Выбрать Certificate Location в качестве Local
Computer и Store Name в качестве
Personal.
- Щелкнуть Select Certificate from Store.
- Выбрать сертификат, необходимый для декодирования/подписания сообщения.
- Щелкнуть Open Private Key File Properties.
- На вкладке Security добавить или учетную запись «ASPNET»
(если выполняется IIS 5) или учетную запись «Network Service» (если
выполняется IIS 6), и затем выбрать опцию Read.
Это в основном изменяет права доступа к хранилищу секретных ключей для
учетной записи ASP.NET. Без этого ASP.NET не будет иметь прав доступа к файлу
секретного ключа и, следовательно, не сможет осуществить декодирование. Именно
этому вопросу посвящен раздел справочника в документации WSE 2
(ms-help://MS.WSE.1033/wse/html/gxaconmanagingx509certificates.htm).
Установка безопасного сеанса для обмена многими
сообщениями
Приводимые до сих пор политики определяли требования WS-Security для
обеспечения аутентификации, целостности и конфиденциальности отдельного
сообщения. Спецификация WS-Security не касается того, как устанавливать
безопасные сеансы, которые могут использоваться для безопасного обмена сериями
сообщений. Этим занимается спецификация WS-SecureConversation, которая
определяет SSL-подобную функциональность для Web-сервисов. Она сосредотачивается
на безопасном содержимом, в рамках которого можно вычислять и передавать «общие
ключи», используемые для обеспечения безопасности общения со многими
сообщениями. WSE 2 включает пример реализации WS-SecureConversation, и ее
реализация WS-Policy позволяет декларативно определять требования для
безопасного сеанса, осуществляемые WSE.
Общее безопасное содержимое представлено
SecurityContextToken (SCT), который распределен между
сообщающимися сторонами на период существования «сеанса безопасной связи». Он
содержит общий симметричный «секретный ключ». Будучи аутентифицированным (и до
тех пор, пока не истечет срок действия), SecurityContextToken
может использоваться для подписания и/или кодирования сообщений с помощью
симметричного секретного ключа (или производного от него симметричного ключа).
Как упоминалось ранее, это намного более эффективно, чем использование
асимметричного ключа.
SecurityContextToken обычно создается доверительным сервисов
выпуска маркеров доступа в соответствие со спецификацией WS-Trust. Инициатор
отправляет подписанный RequestSecurityToken (RST) издателю
маркера, который идентифицирует другую сторону, с которой хочет установить
связь. Издатель маркера отправляет назад
RequestSecurityTokenResponse (RSTR), подписанный издателем
маркера. Обратите внимание, что встроенный издатель маркера для выпуска
SecurityContextTokens в WSE зашифрует RSTR для инициатора.
Таким образом, важно, что маркер, используемый инициатором для подписания
RequestSecurityToken, допускает кодирование.
RequestSecurityTokenResponse содержит
SecurityContextToken, включающий секрет, закодированный для
другой стороны, и секрет для инициатора. Теперь инициатор может отправлять
сообщения другой стороне, подписанные и/или закодированные с помощью общего
секрета и содержащие SecurityContextToken. Рисунок, приведенный
ниже, показывает обмен в случае использования для подписания
RequestSecurityToken и подписания/кодирования
RequestSecurityTokenResponse сертификатов X.509.
Рис. 1. Установление SCT через сервис издающий
маркеры
Инициатор может способствовать этому обмену программно или создавая политику.
Показанная ниже политика заставляет WSE получать и использовать
SecurityContextToken от имени инициатора — в данном случае,
клиента Web-сервиса — при обмене информацией с Web-сервисом.
<policyDocument
xmlns="http://schemas.microsoft.com/wse/2003/06/Policy">
<mappings>
<map to="http://localhost/policyapp/secureservice2.asmx">
<default policy="#SignAndEncryptBodyWithSCT" />
</map>
<map to="http://localhost/policyapp/secureConversation.ashx">
<default policy="#SignRSTWithX509Certificate" />
</map>
</mappings>
<policies
xmlns:wsu="http://schemas.xmlsoap.org/ws/2002/07/utility"
xmlns:wsp="http://schemas.xmlsoap.org/ws/2002/12/policy">
<wsp:Policy wsu:Id="SignAndEncryptBodyWithSCT">
<Integrity wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenInfo>
<SecurityToken>
<TokenType>SecurityContextToken</TokenType>
<TokenIssuer>
http://localhost/policyapp/secureConversation.ashx
</TokenIssuer>
</SecurityToken>
</TokenInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
</Integrity>
<Confidentiality wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<KeyInfo>
<SecurityToken>
<TokenType>SecurityContextToken</TokenType>
<TokenIssuer>
http://localhost/policyapp/secureConversation.ashx
</TokenIssuer>
</SecurityToken>
</KeyInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
</Confidentiality>
</wsp:Policy>
<wsp:Policy wsu:Id="SignRSTWithX509Certificate">
<Integrity wsp:Usage="wsp:Required"
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<TokenInfo>
<SecurityToken>
<TokenType>X509v3</TokenType>
<Claims>
<SubjectName>CN=WSE2QuickStartClient</SubjectName>
</Claims>
</SecurityToken>
</TokenInfo>
<MessageParts
Dialect="http://schemas.xmlsoap.org/2002/12/wsse#part">
wsp:Body()
</MessageParts>
</Integrity>
</wsp:Policy>
</policies>
</policyDocument>
Заметьте, что конечная точка в
http://localhost/policyapp/secureConversation.ashx
конфигурирована с использованием политики, ID которой —
SignRSTWithX509Certificate. Эта конечная точка представляет
издающий маркеры сервис. Эта политика заставляет WSE посылать
RequestSecurityToken, подписанный заданным сертификатом X.509,
в издающий маркеры сервис.
Издающий маркеры сервис, предоставленный WSE, реализован как HTTP-обработчик
ASP.NET. чтобы увидеть, как конфигурирован издающий маркеры сервис, посмотрите
на приведенный здесь файл Web.config Web-сервиса.
<configuration>
...
<microsoft.web.services>
...
<tokenIssuer>
<serverToken>
<KeyInfo xmlns="http://www.w3.org/2000/09/xmldsig#">
<SecurityTokenReference
xmlns="http://schemas.xmlsoap.org/ws/2002/12/secext">
<!-- CN=WSE2QuickStartServer -->
<KeyIdentifier ValueType="X509v3">
bBwPfItvKp3b6TNDq+14qs58VJQ=
</KeyIdentifier>
</SecurityTokenReference>
</KeyInfo>
</serverToken>
</tokenIssuer>
</microsoft.web.services>
<system.web>
...
<httpHandlers>
<add verb="*" path="secureConversation.ashx"
type="Microsoft.Web.Services.Security.SecureConversation.
SecurityContextTokenService,
Microsoft.Web.Services, Version=2.0.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</httpHandlers>
</system.web>
</configuration>
Обратите внимание, что, хотя издающий маркеры сервис может быть
конфигурирован так, чтобы они с целевым Web-сервисом находились в разных
виртуальных директориях, в данном случае они располагаются в одной виртуальной
директории. Оказывается, это обеспечивает целевому Web-сервису
«конфиденциальную» информацию об общем секрете, ассоциированную с любым
SecurityContextToken, выпущенным издающим маркеры сервисом от
его имени. Это значит, что SecurityContextToken, выпущенные в
этом примере, не содержат общего секрета. Элемент tokenIssuer
описывает сертификат издателя маркеров, используемый для подписания
RequestSecurityTokenResponse. В данном случае сертификат X.509
должен иметь секретный ключ и быть доступным из рабочего процесса ASP.NET.
Конечная точка Web-сервиса конфигурирована, исходя из политики, имеющей ID —
SignAndEncryptBodyWithSCT. Это обусловливает то, что все
сообщения, отправляемые Web-сервису, должны быть подписаны и закодированы с
помощью SecurityContextToken, возвращенного издающим маркеры
сервисом. Фрагмент кода, приведенный ниже, показывает, насколько прост код
клиента Web-сервиса.
SecureService2Wse s2 = new SecureService2Wse();
s2.method1("Hello ");
s2.method2("World");
В данном случае method1 и method2
выполняются в рамках одного и того же контекста безопасности.
Использование редактора WSE-политики
На самом деле существует GUI-инструмент редактора политики, поставляемый с
WSE 2.0. он называется WsePolicyEditor.exe и находится в подкаталоге
Tools\PolicyEditor директории установки WSE 2.0.
Написание и конфигурирование специальных
утверждений
Если рассмотренные здесь стандартные утверждения политики не удовлетворяют
вашим требованиям, тогда можно создать обработчики специальных утверждений
политики, которые как раз будут подходить инфраструктуре политики WSE. Однако в
предварительной версии WSE 2.0 то, как это сделать, не задокументировано в
достаточной мере.
Заключение
Семейство спецификаций WS-Policy предоставляет стандартный способ выражения
требований, возможностей и предпочтений приложений Web-сервисов и упрощает для
них процесс «ознакомления» друг с другом. Их способная взаимодействовать
декларативная природа обеспечивает инфраструктуре Web-сервисов возможность
предоставлять поддержку для внедрения утверждений политики от имени приложения
Web-сервиса, и тогда разработчику приходится писать намного меньшее количество
кода. Вот что именно делает WSE 2.0: сегодня он обеспечивает поддержку некоторых
утверждений, определенных в спецификации WS-SecurityPolicy, а также
предоставляет расширяемый механизм, позволяющий так же обрабатывать специальные
утверждения.
Никакая часть настоящей статьи не может быть воспроизведена или
передана в какой бы то ни было форме и какими бы то ни было средствами, будь то
электронные или механические, если на то нет письменного разрешения владельцев
авторских прав.
Материал, изложенный в данной статье, многократно
проверен. Но, поскольку вероятность технических ошибок все равно существует,
сообщество не может гарантировать абсолютную точность и правильность приводимых
сведений. В связи с этим сообщество не несет ответственности за возможные
ошибки, связанные с использованием статьи.
|
|
|
|
|
|
|