Windows Workflow

Защита сервисов рабочих процессов в WF 4

Зульфигар Ахмед

Загрузка примера кода

Windows Workflow Foundation (WF) позволяет писать программную логику с помощью визуальных средств. Как только программная логика реализована в виде рабочего процесса (workflow), ее можно выполнять после размещения этого процесса в хосте. Сервис рабочего процесса (workflow service) — особый тип веб-сервиса, реализованный с применением рабочего процесса и доступный потребителю благодаря хостингу в WorkflowServiceHost. В этой статье мы поговорим о вариантах защиты различных хостов рабочих процессов, уделяя большее внимание сервисам рабочих процессов и WorkflowServiceHost. Я расскажу о некоторых ключевых точках расширения, которые можно использовать для включения в границы защиты сервисов рабочих процессов уровня рабочих процессов. Я также рассмотрю проект Workflow Security Pack (WFSP) и покажу, как с помощью его набора операций можно создавать комплексную защиту решений на основе рабочих процессов. WF 4, которая поставляется с Microsoft .NET Framework 4, предоставляет расширяемый API хостинга и содержит в готовом виде три хоста с разными возможностями.

WorkflowInvoker Это самый базовый хост с наименьшими возможностями, который предоставляет простой API для запуска рабочих процессов. Объект WorkflowInvoker поддерживает только один экземпляр рабочего процесса, переданный через конструктор или статический метод Invoke. Данный хост гарантирует все выполнение рабочего процесса в том же вызвавшем потоке, поэтому, если вызвавший код олицетворяет конкретный контекст защиты, все операции будут выполняться в этом контексте. WorkflowInvoker не является хостом рабочего процесса в истинном смысле — он скорее инкапсулирует хост на базе WorkflowApplication и использует контекст синхронизации на основе прокачки сообщений (pump-based synchronization context), чтобы предоставить простой в применении API с согласованной семантикой выполнения. Например, исключения, транзакции прозрачно пересекают границы вызова (invocation boundary). Такое поведение упрощает защиту, поскольку в ходе всего выполнения рабочего процесса доступен контекст защиты вызвавшего кода и операции могут использовать его в разнообразных вариантах обеспечения безопасности. В частности, с WorkflowInvoker без проблем работает авторизация на основе участников системы безопасности и разрешений (Principal-Permission) и делегирование Kerberos.

WorkflowApplication Это хост с несколько большими возможностями, тем не менее он тоже поддерживает только один экземпляр. Этот хост выполняет рабочий процесс, используя потоки ввода-вывода из CLR-пула ThreadPool. Контекст защиты вызвавшего потока не копируется в поток рабочего процесса, поэтому, даже если осуществляется олицетворение клиента рабочего процесса, оно не будет распространяться на WF-поток, который выполняет операции. Контекст защиты вызвавшего потока можно распространить на WF-поток, задействовав собственный контекст синхронизации, который пересылал бы вызов в тот же входящий поток Async аналогично контексту синхронизации, используемому WorkflowInvoker:

public class MySyncContext : SynchronizationContext
{
  public override void Post(SendOrPostCallback d, object state)
  {
    d(state);
  }
}

WorkflowServiceHost Это хост с наиболее обширными возможностями, предоставляющий среду хостинга для нескольких экземпляров рабочего процесса. Как уже говорилось, WF-сервисы являются особым типом веб-сервисов, реализация которых основана на рабочих процессах. WorkflowServiceHost наследует от стандартного WCF-класса ServiceHostBase, и к WorkflowServiceHost применимы все концепции защиты WCF. Операции обмена сообщения (messaging activities) — основная модель взаимодействия, поддерживаемая WorkflowServiceHost, наряду с WorkflowHostingEndpoint, который позволяет использовать WorkflowServiceHost без операций обмена сообщениями. В этой статье я в основном сосредоточусь на аспектах защиты операций обмена сообщениями, WF-сервисов и WorkflowServiceHost. Обзор технологии сервисов рабочих процессов см. в статье Леона Велички (Leon Welicki) «Visual Design of Workflows with WCF and WF 4» в номере MSDN Magazine за май 2010 г.(msdn.microsoft.com/magazine/ff646977).

Сетевая защита сервисов рабочих процессов

Поскольку сервисы рабочих процессов являются стандартными WCF-сервисами, аспекты сетевой защиты настраиваются с помощью стандартных WCF-механизмов привязки. Сервис рабочего процесса можно предоставлять через одну или несколько конечных точек, используя конкретную привязку в зависимости от требований сервиса к безопасности. WCF-конвейер диспетчеризации (dispatch pipeline) будет выполняться, только если входящее сообщение удовлетворяет требованиям целевой конечной точки к безопасности. Логика рабочего процесса выполняется в самом конце конвейера диспетчеризации, поэтому все точки расширения WCF применимы и к сервисам рабочих процессов. Например, через стандартную точку расширения ServiceAuthorizationManager авторизацию можно распространить на сервисы рабочих процессов. Инфраструктуры вроде Windows Identity Foundation (WIF) интегрируются с WCF на уровне диспетчера (dispatcher level), поэтому их тоже можно прозрачно использовать с этими сервисами. Есть некоторые различия, связанные с потоками и относящиеся к нескольким точкам асинхронности между уровнями WCF и WF, что затрудняет реализацию в сервисах рабочих процессов некоторых сценариев применения локальной памяти потока (Thread Local Storage, TLS). Например, WIF предоставляет информацию о входящей идентификации через Thread.CurrentPrincipal и корректно задает ее для сервисов на основе кода (code-based services). Однако ваша логика рабочего процесса может в конечном счете выполняться в потоке, отличном от исходного WCF-потока. Если так и произойдет, все данные, хранящиеся в TLS, в том числе Thread.CurrentPrincipal, окажутся недостоверными, поэтому в рабочих процессах рекомендуется не полагаться на TLS. О некоторых способах решениях этой проблемы мы еще поговорим.

WF 4 также предоставляет операцию Send для вызова из рабочего процесса других веб-сервисов. Эту операцию можно конфигурировать привязкой, которая будет использоваться при вызове других сервисов из рабочего процесса. На внутреннем уровне операцию Send посылает сообщения через стандартный WCF ChannelFactory/Channel API, и для создания этой внутренней фабрики каналов применяется соответственно сконфигурированная привязка. В операцию Send также встроен уровень кеширования для ChannelFactory/Channel. По умолчанию этот уровень используется, только если информация конечной точки указывается напрямую через свойства операции Send и выбирается готовая привязка, как показано на рис. 1.

Рис. 1. Свойства операции Send

Как только информация конечной точки загружается из конфигурационного файла с помощью свойства EndpointConfigurationName, безопасное кеширование отключается и при каждом выполнении операции Send создается совершенно новый ChannelFactory. Защищенный привязки, такие как wsHttpBinding и wsFederationHttpBinding, проделывают немалый объем работы на этапе открытия фабрики каналов, и повторное создание фабрики каналов для каждого сообщения может оказаться весьма дорогостоящим. Так, стандартная привязка WSHttpBinding оптимизирована для максимальной производительности и безопасности, а достигается это установлением защищенного сеанса, который и создает наибольшие издержки.Последующие сообщения можно защищать с гораздо меньшими издержками. Без кеширования ChannelFactory это поведение WSHttpBinding перестает быть оптимальным, так как для каждого прикладного сообщения посылаются четыре дополнительных сообщения инфраструктуры (табл. 1), чтобы согласовать удостоверения сервиса, а затем устанавливается защищенный сеанс.

Табл. 2. Сообщения инфраструктуры, посылаемые для согласования удостоверений сервиса

http://schemas.xmlsoap.org/ws/2005/02/trust/RST/Issue
http://schemas.xmlsoap.org/ws/2005/02/trust/RSTR/Issue
http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT
http://tempuri.org/IPingService/Ping
http://schemas.xmlsoap.org/ws/2005/02/trust/RST/SCT/Cancel

В WF 4 любая конфигурация привязки, загруженная из конфигурационного файла (даже в случае стандартных привязок), считается операцией Send «небезопасной для кеширования», и кеширование ChannelFactory отключается. Это поведение по умолчанию можно переопределить включением небезопасного кеширования канала, при котором ChannelFactory будет использоваться повторно при отправке сообщений той же конечной точке. Поведение сервиса SendMessageChannelCache разрешает небезопасное кеширование, а также позволяет настраивать различные параметры кеша Channel и ChannelFactory, как показано ниже:

<serviceBehaviors>
  <behavior>
    <sendMessageChannelCache allowUnsafeCaching="true">
      <channelSettings idleTimeout="1:0:0" maxItemsInCache="60"/>
      <factorySettings idleTimeout="1:0:0" maxItemsInCache="60"/>
    </sendMessageChannelCache>
  </behavior>
</serviceBehaviors>

Где мой OperationContext?

В традиционных сервисах на основе кода информация, связанная с защитой для входящего вызова, доступна через OperationContext.Current. Перед вызовом метода сервиса исполняющая среда WCF-диспетчера (WCF dispatcher runtime) проверяет, установлен ли OperationContext в потоке, чтобы внутри метода сервиса информация защиты была доступна через OperationContext.Current.

Сервисы рабочих потоков вводят дополнительную сложность, так как между диспетчеризацией WCF и выполнением рабочего процесса появляется целый набор асинхронных точек. В любой из этих точек может произойти переключение потока, и тогда логика (операции) рабочего процесса будут выполняться в потоке, отличном от WCF-потока, а OperationContext окажется недоступен через OperationContext.Current. В WF 4 появилась возможность независимого от конкретного потока доступа к OperationContext с применением механизма обратных вызовов, основанного на IReceiveMessageCallback и ISendMessageCallback. Первый используется на серверной стороне, а второй открывает доступ к OperationContext на клиентской стороне. На серверной стороне объекты IReceiveMessageCallback вызываются сразу после приема сообщения операцией Receive. Чтобы подключить эти обратные вызовы к операциям Send и Receive, их нужно сделать доступными как свойства выполнения (execution properties) при работе Send/Receive. Стандартный подход к добавлению свойств выполнения в операцию — создание операции с родительской областью видимости (parent scope activity) и установка свойств выполнения в ходе работы родительской операции, как показано на рис. 2.

Рис. 3. Операция для добавления свойств выполнения

[ContentProperty("Body")]
public sealed class OperationContextScope : NativeActivity
{
  public Activity Body { get; set; }
  protected override void Execute(NativeActivityContext context)
  {
    if (this.Body != null)
    {
      // Adding an execution property to handle OperationContext
      context.Properties.Add(OperationContextScopeProperty.Name,
        new OperationContextScopeProperty());
      context.ScheduleActivity(this.Body);
    }
  }
}

В фрагменте кода на рис. 2 при выполнении операции OperationContextScope к контексту просто добавляется свойство выполнения, чтобы все дочерние операции видели это свойство. Операции Send и Receive ищут ранее упомянутые свойства обратного вызова, и, если обнаруживается одно из этих свойств, оно вызывается на правильной стадии обработки сообщения, обеспечивая вам доступ к OperationContext. В этом примере любая операция Receive, входящая в ту же область действия, видит OperationContextScopeProperty и выполняет обратный вызов, передавая значение в OperationContext (рис. 3).

Рис. 4. ReceiveMessageCallback, реализованный как свойство выполнения

[DataContract]
class OperationContextScopeProperty : IReceiveMessageCallback,  IExecutionProperty
{
  private OperationContext current;
  private OperationContext orignal;

  public static readonly string Name = 
    typeof(OperationContextScopeProperty).FullName;
  public void OnReceiveMessage(OperationContext operationContext, 
    ExecutionProperties activityExecutionProperties)
  {
    current = operationContext;
    operationContext.OperationCompleted 
      += delegate(object sender, EventArgs e)
    {
      current = null;
    };
  }

  public void CleanupWorkflowThread()
  {
    OperationContext.Current = orignal;
  }
  public void SetupWorkflowThread()
  {
    orignal = OperationContext.Current;
    OperationContext.Current = current;
    }
}

OperationContextScopeProperty просто захватывает и сохраняет текущий активный OperationContext, а впоследствии назначает его нужному WF-потоку, используя WF-механизм TLS. В интерфейсе IExecutionProperty есть методы Setup/CleanUpWorkflowThread, которые вызываются до и после выполнения каждого рабочего элемента WF (операции) и дают возможность задавать различные, связанные с TLS свойства в выбранном WF-потоке; один из примеров в данном случае — OperationContext.

OperationContextScope — пример собственной операции, которая использует расширяемость WF 4 для поддержки независимого от конкретного потока доступа к WCF OperationContext для всех дочерних операций в области видимости.

Workflow Services и WIF

WIF предоставляет богатый API и объектную модель для WCF-сервисов и ASP.NET-приложений с поддержкой заявок (claims). WIF интегрируется с WCF на уровне хоста, поэтому большая часть средств WIF работает и с Workflow Services. Подробнее об интеграции WIF с Workflow Services читайте в моей статье в блоге bit.ly/a6pWgA. Готовый вариант интеграции прекрасно работает в базовых сценариях применения, а для более сложных случаев можно использовать операции из WFSP.

Знакомство с WFSP CTP 1

WFSP Community Technology Preview (CTP) 1 содержит набор операций и соответствующее WCF-поведение для поддержки ключевых вариантов защиты в WF 4. В WFSP для реализации многих возможностей используется модель расширения ISend/IReceiveMessageCallback. WFSP версии CTP 1 был опубликован на сайте CodePlex в июле 2010 г., и его можно скачать по ссылке wf.codeplex.com/releases/view/48114.

Операции в WFSP, показанные на рис. 4, отлично «смешиваются» с остальной частью WF и предоставляют мощные конструкции, обеспечивающие интегрированную защиту в решениях на основе рабочих процессов.

image: Workflow Security Pack Activities

Рис. 5. Операции в Workflow Security Pack

Авторизация внутри рабочего процесса

В Workflow Services можно использовать расширяемость стандартного WCF ServiceAuthorizationManager, чтобы вводить в действие авторизацию, и этот компонент работает точно так же, как в сервисах на основе кода. Однако в некоторых ситуациях (например, где данные авторизации являются частью рабочего процесса) вы предпочтете отложить решение об авторизации до реального выполнения рабочего процесса. PrincipalPermissionScope — операция на серверной стороне, которая вводит в рабочие процессы CLR-средство авторизации PrincipalPermission. Любая дочерняя операция, помещенная в область ее видимости, будет выполняться, только если запрос разрешения завершится успешно. Эта операция ищет информацию об идентификации во входящем WCF-контексте защиты, доступ к которому осуществляется из OperationContext. PrincipalPermissionScope реализован на основе того же механизма IReceiveMessageCallback, о котором я рассказывал ранее в этой статье.

Реальный запрос PrincipalPermission сверяется с объектом IPrincipal на основе значения ServiceAuthorizationBehavior.PrincipalPermissionMode. Это средство расширения позволяет PrincipalPermissionScope работать с провайдером ролей ASP.NET, а также с собственной реализацией IPrincipal, созданной с помощью собственной реализации IAuthorizationPolicy. Подробнее о конфигурации провайдера ролей ASP.NET в случае WCF-сервиса см. по ссылке msdn.microsoft.com/library/aa702542.

Операции обмена сообщениями и аутентифицированный обмен сообщениями

Операция Send — основной способ использования веб-сервисов из рабочих процессов. В большинстве ситуаций на практике эти внутренние сервисы защищаются и требуют аутентификации до выполнению какой-либо работы. В стандартных сервисах на основе кода удостоверения защиты указываются через свойство ClientCredential, предоставляемое ChannelFactory и производным классом прокси ClientBase<T>. С помощью этого свойства клиент может сообщить нужное удостоверение перед вызовом сервиса. К сожалению, в WF 4 операция Send, которая обертывает ChannelFactory, не предоставляет свойство ClientCredential, поэтому некоторые сценарии применения, где необходимо явно указывать определенные удостоверения, невозможны при использовании стандартной операции Send. Заметьте, что Send получает конфигурацию поведения конечной точки из конфигурационного файла, а значит, вы можете создать собственное поведение конечной точки, чтобы задать нужные удостоверения.

Типичный пример ситуации, где нужно явно указывать удостоверения, — вызов сервиса, сконфигурированного на требование имени пользователя и пароля. Так как свойство ClientCredential не предоставляется операцией Send, возможности задать эти удостоверения нет. Рассмотрим, как эта проблема в данной и других ситуациях решается с помощью операции GetUserNameSecurityToken из WFSP.

На рис. 5 операция генерируется мастером Add Service Reference и настраивается на вызов сервиса, защита которого требует аутентификации по имени пользователя (маркеру UserName), как показано в следующей конфигурации привязки:

<wsHttpBinding>
  <binding name="singleShotUserName">
    <security mode="Message">
      <message clientCredentialType="UserName" establishSecurityContext
        ="false" />
    </security>
  </binding>
</wsHttpBinding>

image: Authenticated Messaging Using a UserName Token

Рис. 6. Аутентифицированный обмен сообщениями с применением маркера UserName

В предыдущем рабочем процессе GetUserNameSecurityToken создает UserNameSecurityToken на основе предоставленного UserName/Password и включает его в SecurityTokenHandle, предоставляемый операцией TokenFlowScope. Workflow Security Pack применяет защиту на уровне SecurityToken в противоположность ChannelFactory/ClientBase<T>, где защита работает на уровне удостоверений. В стандартной WCF удостоверения используются для создания маркеров защиты, но в WFSP маркеры защиты применяются напрямую и подключаются к уровню защиты WCF на уровне маркеров, а не удостоверений.

TokenFlowScope — ключевая операция, обеспечивающая поддержку аутентифицированного обмена сообщениями и других интересных сценариев применения. Эта операция наряду с поведением конечной точки WorkflowClientCredentials передает включенные маркеры с уровня рабочего процесса на уровень защиты WCF, где они присоединяются к исходящему сообщению для каждой привязки индивидуально, как того требует конечная точка. TokenFlowScope требует сконфигурировать собственное поведение ClientCredential (WorkflowClientCredentials), как показано в следующем фрагменте конфигурации:

<behavior>
   <!--This custom clientCredentials enables the credential flow from 
     workflow data model into WCF security layer. -->
   <clientCredentials
     type="Microsoft.Security.Activities.WorkflowClientCredentials, 
     Microsoft.Security.Activities, Version=1.0.0.0, Culture=neutral, 
     PublicKeyToken=31bf3856ad364e35">
   </clientCredentials>
</behavior>

WFSP следует именно этой модели при вызове сервиса, который требует передачи маркера от Security Token Service (STS), как показано на рис. 6.

image: Fine-Grained Control of SAML Token Acquisition and Usage

Рис. 7. Тонкое управление получением и использованием SAML-маркера

На рис. 6 GetSamlSecurityToken обращается к издателю и получает SAML-маркер, который потом включается в описатель (handle), предоставляемый операцией TokenFlowScope. Это включение делает маркер доступным любой операции Send, находящейся в той же области видимости и требующей передачи SAML-маркера. Данная модель расширяема, и GetSamlSecurityToken сам может использовать уже включенный маркер, запрашивая SAML-маркер, например, если STS требует маркер UserName для возврата SAML-маркера и если в область видимости уже включен допустимый маркер UserName. GetSamlSecurityToken, сконфигурированный поведением WorkflowClientCredentials, будет использовать этот маркер при запросе SAML-маркера.

«Из коробки» WFSP поддерживает только UserName и SAML-маркеры; однако вы можете обеспечить поддержку и других типов маркеров, наследуя от класса GetSecurityToken, как показано в фрагменте кода на рис. 7, где реализована операция, создающая маркер на основе сертификата X509.

Рис. 8. Расширяемость WFSP: реализация поддержки дополнительных типов маркеров

[Designer(typeof(GetX509SecurityTokenDesigner))]
public class GetX509SecurityToken : GetSecurityToken
{
  public GetX509SecurityToken()
  {
    FindType = X509FindType.FindBySubjectName;
    StoreLocation = StoreLocation.CurrentUser;
    StoreName = StoreName.My;
  }

  public InArgument<X509Certificate2> Certificate { get; set; }
  public X509FindType FindType { get; set; }
  public StoreLocation StoreLocation { get; set; }
  public InArgument<string> FindValue { get; set; }
  public StoreName StoreName { get; set; }

  protected override void Execute(NativeActivityContext context)
  {
    X509Certificate2 targetCert = null;
    if (this.Certificate != null)
      targetCert = this.Certificate.Get(context);
    if (targetCert == null)
    {
      var store = new X509Store(StoreName, StoreLocation);
      try
      {
        store.Open(OpenFlags.ReadOnly);
        var col = store.Certificates.Find(FindType, FindValue.Get(context), false);
        if (col.Count > 0)
          targetCert = col[0];//Use first certificate mathing the search criteria
      }
      finally
      {
        if (store != null)
          store.Close();
      }
    }
    if (targetCert == null)
      throw new InvalidOperationException(
        "No certificate found using the specified find criteria.");
        // Enlist the token as a flow token
      base.EnlistSecurityToken(context, new X509SecurityToken(targetCert));
  }
}

GetX509SecurityToken создает маркер X509Security на основе сертификата и включает его в SecurityTokenHandle как маркер, применимый для вызова сервиса, требующего сертификат для аутентификации. На рис. 8 показано, как используется GetX509SecurityToken с дизайнером собственной операции.

image: TokenFlowScope with a Custom GetToken Activity

Рис. 9. TokenFlowScope с собственной операцией GetToken

Делегирование на основе заявок

Делегирование на основе заявок (claims-based delegation) — еще одно полезное средство, поддерживаемое WFSP. Такое делегирование зачастую более желательно для сервисов на основе рабочих потоков, так как эти сервисы реализуют в основном процесс управления или бизнес-процесс, из которого вызывается множество внутренних сервисов. Кроме того, для принятия решений об авторизации разного уровня этим внутренним сервисам часто нужен доступ к идентификации вызвавшего. WFSP использует функциональность ActAs в WS-Trust 1.4, чтобы маркер любого типа можно было использовать как маркер ActAs. По умолчанию все операции GetToken создают маркер и включают его обычным образом, но все они поддерживают флаг IsActAsToken, как показано на рис. 9.

image: Creating an ActAs Token

Рис. 10. Создание маркера ActAs

Когда этот флаг установлен, логика создания маркера остается прежней, но созданный маркер T1 включается как ActAs, а не как обычный. В одной области видимости может быть только один маркер ActAs, и он используется операцией GetSamlSecurityToken при запросе SAML-маркера. При выполнении GetSamlSecurityToken активный маркер ActAs передается как часть сгенерированного этой операцией запроса на выдачу маркера. Возвращаемый маркер T2 будет содержать заявки как из маркера аутентификации, так и маркера ActAs. Наконец, любая операция Send, выполняемая в этой области, может использовать маркер T2 при вызове внутреннего сервиса, который увидит обе идентификации в своем контексте защиты.

Операция GetBootstrapToken применяется на промежуточном уровне для поддержки всего процесса делегирования на основе заявок. В противоположность операциям GetToken эта операция просто считывает содержимое входящего маркера и включает его как маркер ActAs вместо того, чтобы создавать новый маркер, а потом уже включать его. Операция GetBootstrapToken позволяет сервису на основе рабочего процесса использовать идентификацию вызвавшего в дополнение к собственной идентификации при обращениях к внутренним сервисам, как показано на рис. 10.

image: End-to-End Claims-Based Delegation Flow

Рис. 11. Полная схема делегирования на основе заявок

На этапе 3 на схеме с рис. 10 WF-сервис использует операции WFSP для чтения содержимого входящего начального маркера (bootstrap token), получает новый маркер, действующий как идентификация начального маркера, а затем передает обе идентификации внутреннему сервису. Рабочий процесс, используемый этим WF-сервисом, показан на рис. 11.

image: Claims-Based Delegation Workflow

Рис. 12. Рабочий процесс делегирования на основе заявок

В рабочем процессе на рис. 12 операция GetBootstrap помещается в OperationContextScope, чтобы обеспечить при выполнении этой операции независимый от потоков доступ к OperationContext. GetSamlSecurityToken использует маркер ActAs, созданный на предыдущем этапе операцией GetBootstrapToken, а затем операция Echo вызывает внутренний сервис с конечным SAML-маркером, сгенерированным операцией GetSamlSecurityToken.

Олицетворение/делегирование в Windows

ImpersonatingReceiveScope — еще одна операция на серверной стороне, которая вводит в мир рабочих процессов олицетворение и делегирование из Windows. При выполнении эта операция ищет WindowsIdentity во входящем контексте защиты. Если входящее сообщение создает WindowsIdentity, все дочерние операции, являющиеся частью тела этого сообщения, будут выполняться в данной олицетворяемой области. ImpersonatingReceiveScope использует упомянутый ранее механизм Workflow TLS, чтобы олицетворять (подменять) идентификацию в WF-потоке перед самым выполнением рабочего элемента. По окончании выполнения этого рабочего элемента олицетворение возвращается в исходное состояние.

Если найти допустимый WindowsIdentity во входящем контексте защиты не удалось, ImpersonatingReceiveScope ищет заявку UPN — либо в идентификации WIF (Thread.CurrentPrincipal), либо в традиционном WCF ClaimsSet — и использует ее для создания WindowsToken, применяя функционал S4U из Kerberos. При преобразовании заявки UPN в Windows-маркер ImpersonatingReceiveScope полагается на «Claims to Windows Token Service» — часть исполняющей среды WIF. Для успешного преобразования заявки в маркер вы должны установить и запустить этот сервис.

На рис. 13 показан пример типичного использования операции ImpersonatingReceiveScope.

image: ImpersonatingRecieveScope in Action

Рис. 13. ImpersonatingRecieveScope в действии

Комплексная защита

Для внешних потребителей WF-сервисы являются стандартными WCF-сервисами и поэтому к ним применимо большинство вариантов защиты WCF. В WF 4 появилось несколько ключевых точек расширения, с помощью которых границы защиты WF-сервисов можно распространить на уровень рабочих процессов. WFSP предоставляет набор операций, использующих эти точки расширения для создания комплексной защиты в WF 4.

Зульфигар Ахмед (Zulfiqar Ahmed) — старший консультант в группе Premier Support for Developers и первый автор проекта Workflow Security Pack. Ведет блог на zamd.net, где пишет по самой разной тематике — от Windows Communication Foundation, Windows Workflow Foundation и защиты на основе заявок до общих вопросов, связанных с Microsoft .NET Framework.

Выражаю благодарность за рецензирование статьи эксперту Дэйву Клиффу (Dave Cliffe)