Делегирование и олицетворение с использованием WCF

Олицетворение - это стандартная техника, которую службы используют для ограничения клиентского доступа к ресурсам домена службы. В роли ресурсов домена службы могут выступать ресурсы компьютера, например локальные файлы (олицетворение), или ресурсы, расположенные на другом компьютере, например общая папка (делегирование). Пример приложения см. в разделе Impersonating the Client. Пример использования олицетворения см. в разделе How to: Impersonate a Client on a Service.

Внимание

Следует иметь в виду, что при олицетворении клиента в службе служба выполняется с учетными данными клиента, которые могут иметь более высокий уровень разрешений, чем серверный процесс.

Обзор

Обычно клиенты вызывают службы, чтобы платформа службы выполнила какие-либо действия от имени клиента. Олицетворение позволяет службе выступать в качестве клиента при выполнении такого действия. Делегирование позволяет внешней службе перенаправить запрос клиента внутренней службе таким образом, чтобы внутренняя служба также могла олицетворять клиент. Олицетворение чаще всего используется, чтобы проверить, имеет ли клиент разрешение на выполнение определенного действия, а делегирование позволяет передать возможности олицетворения, в том числе удостоверение клиента, внутренней службе. Делегирование - это функция домена Windows, которую можно использовать при проверке подлинности Kerberos. Делегирование отличается от потока работы с удостоверениями, а поскольку делегирование позволяет олицетворять клиент даже при отсутствии пароля клиента, эта операция обладает гораздо более широкими правами.

Для олицетворения и делегирования у клиента должно быть удостоверение Windows. Если у клиента нет удостоверения Windows, единственным решением является передача удостоверения клиента второй службе.

Основные принципы олицетворения

Windows Communication Foundation (WCF) поддерживает олицетворение для различных учетных данных клиента. В этом разделе описана поддержка модели служб для олицетворения вызывающего объекта во время реализации метода службы. Также рассматриваются распространенные сценарии развертывания, включающие олицетворение и параметры безопасности SOAP и WCF в этих сценариях.

В этом разделе рассматриваются олицетворение и делегирование в WCF при использовании безопасности SOAP. Вы также можете использовать олицетворение и делегирование с WCF при использовании безопасности транспорта, как описано в разделе "Использование олицетворения с безопасностью транспорта".

Два метода

Безопасность SOAP WCF имеет два различных метода для выполнения олицетворения. Выбор используемого метода зависит от привязки. Первый - олицетворение на основании маркера Windows, получаемого из интерфейса поставщика поддержки безопасности (SSPI) или при проверке подлинности Kerberos, который затем кэшируется службой. Второй метод - олицетворение на основании маркера Windows, получаемого из расширений Kerberos, имеющих общее имя Service-for-User (S4U).

Олицетворение с использованием кэшированного маркера

Для олицетворения с использованием кэшированного маркера используются следующие элементы:

  • привязкиWSHttpBinding, WSDualHttpBindingи NetTcpBinding , а также учетные данные клиента Windows;

  • привязкаBasicHttpBinding , у которой BasicHttpSecurityMode имеет значение TransportWithMessageCredential , или любая другая стандартная привязка, с помощью которой клиент представляет имя пользователя, которое служба может сопоставить с действительной учетной записью Windows;

  • любая привязка CustomBinding , использующая учетные данные клиента Windows, где свойство requireCancellation имеет значение true. (Свойство доступно в следующих классах: SecureConversationSecurityTokenParameters, SslSecurityTokenParametersи SspiSecurityTokenParameters.) Если для привязки используется безопасная беседа, она также должна иметь requireCancellation значение trueсвойства.

  • любая привязка CustomBinding , в которой клиент представляет имя пользователя. При использовании в привязке безопасного обмена данными свойство requireCancellation также должно иметь значение true.

Олицетворение на базе S4U

Для олицетворения на базе S4U используются следующие элементы:

  • привязкаWSHttpBinding, WSDualHttpBindingили NetTcpBinding с учетными данными сертификата клиента, которые служба может сопоставить с действительной учетной записью Windows;.

  • любая привязка CustomBinding , использующая учетные данные клиента Windows, где свойство requireCancellation имеет значение false;

  • любая привязка CustomBinding , использующая имя пользователя или учетные данные клиента Windows, а также безопасный обмен данными, где свойство requireCancellation имеет значение false.

Уровень олицетворения клиента службой зависит от привилегий, доступных учетной записи при попытке олицетворения, используемого типа олицетворения и, возможно, от уровня олицетворения, разрешенного клиентом.

Примечание.

Если клиент и служба выполняются на одном компьютере и клиент выполняется от имени системной учетной записи (например, Local System или Network Service), клиент невозможно олицетворить, если установлен безопасный сеанс с маркерами контекста безопасности с отслеживанием состояния. Приложения Windows Form и консольные приложения обычно выполняются от имени учетной записи находящегося в системе пользователя, поэтому эту учетную запись можно олицетворять по умолчанию. Однако если клиент является страницей ASP.NET и эта страница размещается в IIS 6.0 или IIS 7.0, то клиент выполняется под Network Service учетной записью по умолчанию. Все предоставляемые системой привязки, поддерживающие защищенные сеансы, по умолчанию используют маркеры контекста безопасности с отслеживанием состояния. Однако если клиент является ASP.NET страницей, а также используются безопасные сеансы с использованием STS с отслеживанием состояния, клиент не может быть олицетворен. Дополнительные сведения об использовании scts с отслеживанием состояния в безопасном сеансе см. в разделе "Практическое руководство. Создание маркера контекста безопасности для безопасного сеанса".

Олицетворение в методе службы: декларативная модель

Большинство сценариев олицетворения предполагают выполнение метода службы в контексте вызывающего объекта. WCF предоставляет функцию олицетворения, которая упрощает эту задачу, позволяя пользователю указывать требование олицетворения в атрибуте OperationBehaviorAttribute . Например, в следующем коде инфраструктура WCF олицетворяет вызывающий объект перед выполнением Hello метода. Все попытки обратиться к собственным ресурсам внутри метода Hello окажутся успешными только в том случае, если список управления доступом (ACL) ресурса дает права на доступ вызывающему объекту. Чтобы включить олицетворение, присвойте свойству Impersonation одно из значений перечисления ImpersonationOption : ImpersonationOption.Required или ImpersonationOption.Allowed, как показано в следующем примере.

Примечание.

Если у службы имеется больше прав, чем у удаленного клиента, то используются учетные данные службы, если свойство Impersonation имеет значение Allowed. Это значит, что если пользователь с более узкими правами предоставляет свои учетные данные, то метод выполняется с более широкими правами службы, и пользователь получает доступ к ресурсам, доступ к которым он бы сам получить не смог.

[ServiceContract]
public interface IHelloContract
{
    [OperationContract]
    string Hello(string message);
}

public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        return "hello";
    }
}

<ServiceContract()> _
Public Interface IHelloContract
    <OperationContract()> _
    Function Hello(ByVal message As String) As String
End Interface


Public Class HelloService
    Implements IHelloService

    <OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
    Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
        Return "hello"
    End Function
End Class

Инфраструктура WCF может олицетворить вызывающий объект только в том случае, если вызывающий объект проходит проверку подлинности с учетными данными, которые можно сопоставить с учетной записью пользователя Windows. Если служба настроена на прохождение проверки подлинности с использованием учетных данных, которые невозможно сопоставить с учетной записью Windows, метод службы не выполняется.

Примечание.

В Windows XP олицетворение завершается ошибкой при создании SCT с отслеживанием состояния, что приводит к возникновению InvalidOperationExceptionошибки. Дополнительные сведения см. в разделе "Неподдерживаемые сценарии".

Олицетворение в методе службы: императивная модель

Иногда вызывающему объекту требуется олицетворять не весь метод службы, а лишь его часть. В этом случае необходимо получить удостоверение Windows вызывающего объекта внутри метода службы и императивно выполнить олицетворение. Для этого необходимо с помощью свойства WindowsIdentity объекта ServiceSecurityContext возвратить экземпляр класса WindowsIdentity и вызвать метод Impersonate перед использованием этого экземпляра.

Примечание.

Не забудьте использовать инструкцию Visual BasicUsing или оператор C#using, чтобы автоматически отменить изменения действие олицетворения. Если вы не используете инструкцию или используете язык программирования, отличный от Visual Basic или C#, обязательно отменить изменения уровне олицетворения. В противном случае возникнет угроза атаки типа «отказ в обслуживании» или «несанкционированное получение прав».

public class HelloService : IHelloService
{
    [OperationBehavior]
    public string Hello(string message)
    {
        WindowsIdentity callerWindowsIdentity =
        ServiceSecurityContext.Current.WindowsIdentity;
        if (callerWindowsIdentity == null)
        {
            throw new InvalidOperationException
           ("The caller cannot be mapped to a WindowsIdentity");
        }
        using (callerWindowsIdentity.Impersonate())
        {
            // Access a file as the caller.
        }
        return "Hello";
    }
}
Public Class HelloService
    Implements IHelloService

    <OperationBehavior()> _
    Public Function Hello(ByVal message As String) As String _
       Implements IHelloService.Hello
        Dim callerWindowsIdentity As WindowsIdentity = _
            ServiceSecurityContext.Current.WindowsIdentity
        If (callerWindowsIdentity Is Nothing) Then
            Throw New InvalidOperationException( _
              "The caller cannot be mapped to a WindowsIdentity")
        End If
        Dim cxt As WindowsImpersonationContext = callerWindowsIdentity.Impersonate()
        Using (cxt)
            ' Access a file as the caller.
        End Using

        Return "Hello"

    End Function
End Class

Олицетворение для всех методов службы

В некоторых случаях требуется выполнять в контексте вызывающего объекта все методы службы. Вместо явного включения этой функции для каждого метода в отдельности можно воспользоваться классом ServiceAuthorizationBehavior. Как показано в следующем фрагменте кода, установите свойство ImpersonateCallerForAllOperations равным true. Объект ServiceAuthorizationBehavior извлекается из коллекции расширений функциональности класса ServiceHost . Также обратите внимание, что свойство Impersonation объекта OperationBehaviorAttribute , применяемого к каждому из методов, тоже должно иметь значение Allowed или Required.

// Code to create a ServiceHost not shown.
ServiceAuthorizationBehavior MyServiceAuthorizationBehavior =
    serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
MyServiceAuthorizationBehavior.ImpersonateCallerForAllOperations = true;
' Code to create a ServiceHost not shown.
Dim MyServiceAuthorizationBehavior As ServiceAuthorizationBehavior
MyServiceAuthorizationBehavior = serviceHost.Description.Behaviors.Find _
(Of ServiceAuthorizationBehavior)()
MyServiceAuthorizationBehavior.ImpersonateCallerForAllOperations = True

В следующей таблице описано поведение WCF для всех возможных сочетаний ImpersonationOption и ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Поведение
Обязательное поле Н/Д WCF олицетворяет вызывающего абонента
Допустимо false WCF не олицетворяет вызывающего абонента
Допустимо true WCF олицетворяет вызывающего абонента
NotAllowed false WCF не олицетворяет вызывающего абонента
NotAllowed true Disallowed. (Создается исключение InvalidOperationException .)

Уровень олицетворения, получаемый на основании учетных данных Windows, и олицетворение с использованием кэшированного маркера

В некоторых сценариях при использовании учетных данных клиента Windows клиент может лишь частично управлять уровнем олицетворения в службе. Один из таких сценариев имеет место, когда клиент задает уровень олицетворения Anonymous. Второй сценарий имеет место при олицетворении с использованием кэшированного маркера. Для этого задается свойство AllowedImpersonationLevel класса WindowsClientCredential , к которому происходит обращение как к свойству универсального класса ChannelFactory<TChannel> .

Примечание.

Задание уровня олицетворения Anonymous приводит к тому, что клиент входит в систему службы анонимно. Поэтому служба должна разрешать анонимный вход независимо от того, будет ли выполняться олицетворение.

Клиент может установить один из следующих уровней олицетворения: Anonymous, Identification, Impersonationили Delegation. При этом создается только маркер на заданном уровне, как показано в следующем фрагменте кода.

ChannelFactory<IEcho> cf = new ChannelFactory<IEcho>("EchoEndpoint");
cf.Credentials.Windows.AllowedImpersonationLevel  =
    System.Security.Principal.TokenImpersonationLevel.Impersonation;
Dim cf As ChannelFactory(Of IEcho) = New ChannelFactory(Of IEcho)("EchoEndpoint")
cf.Credentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Impersonation

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

Значение AllowedImpersonationLevel У службы есть SeImpersonatePrivilege Служба и клиент поддерживают делегирование Кэшированный маркер ImpersonationLevel
Анонимные Да Н/Д Олицетворение
Анонимные No Н/Д Идентификация
Идентификация Недоступно Недоступно Идентификация
Олицетворение Да Н/Д Олицетворение
Олицетворение No Н/Д Идентификация
Делегирование Да Да Делегирование
Делегирование Да Нет Олицетворение
Делегирование No Н/Д Идентификация

Уровень олицетворения, получаемый на основании учетных данных имени пользователя, и олицетворение с использованием кэшированного маркера

Передав службу своим именем пользователя и паролем, клиент позволяет WCF входить в систему как этот пользователь, что эквивалентно настройке AllowedImpersonationLevel свойства Delegation. (Доступно AllowedImpersonationLevel в WindowsClientCredential и HttpDigestClientCredential классах.) В следующей таблице представлен уровень олицетворения, полученный при получении учетных данных имени пользователя.

AllowedImpersonationLevel У службы есть SeImpersonatePrivilege Служба и клиент поддерживают делегирование Кэшированный маркер ImpersonationLevel
Недоступно Да Да Делегирование
Недоступно Да Нет Олицетворение
Н/Д No Н/Д Идентификация

Уровень олицетворения при олицетворении на базе S4U

У службы есть SeTcbPrivilege У службы есть SeImpersonatePrivilege Служба и клиент поддерживают делегирование Кэшированный маркер ImpersonationLevel
Да Да Н/Д Олицетворение
Да Нет Н/Д Идентификация
No н/д Недоступно Идентификация

Сопоставление сертификата клиента с учетной записью Windows

Клиент может выполнить свою проверку подлинности в службе с использованием сертификата, чтобы служба сама сопоставила клиент с существующей учетной записью в Active Directory. В следующем примере XML-кода показано, как настроить службы для сопоставления сертификата.

<behaviors>  
  <serviceBehaviors>  
    <behavior name="MapToWindowsAccount">  
      <serviceCredentials>  
        <clientCertificate>  
          <authentication mapClientCertificateToWindowsAccount="true" />  
        </clientCertificate>  
      </serviceCredentials>  
    </behavior>  
  </serviceBehaviors>  
</behaviors>  

В следующем примере кода показано, как настроить службу.

// Create a binding that sets a certificate as the client credential type.  
WSHttpBinding b = new WSHttpBinding();  
b.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;  
  
// Create a service host that maps the certificate to a Windows account.  
Uri httpUri = new Uri("http://localhost/Calculator");  
ServiceHost sh = new ServiceHost(typeof(HelloService), httpUri);  
sh.Credentials.ClientCertificate.Authentication.MapClientCertificateToWindowsAccount = true;  

Делегирование

Чтобы выполнить делегирование внутренней службе, служба должна выполнить многоступенчатую (SSPI без резервной проверки подлинности NTLM) проверку подлинности или прямую проверку подлинности Kerberos во внутренней службе, используя удостоверение Windows клиента. Для делегирования внутренней службе создайте объект ChannelFactory<TChannel> и канал, а затем используйте этот канал для взаимодействия при олицетворении клиента. При такой модели делегирования расстояние, на котором внутренняя служба может располагаться относительно внешней службы, зависит от уровня олицетворения, полученного внешней службой. Если уровень олицетворения равен Impersonation, внешняя и внутренняя службы должны выполняться на одном компьютере. Если уровень олицетворения равен Delegation, внешняя и внутренняя службы могут выполняться как на различных компьютерах, так и на одном компьютере. Для включения олицетворения уровня делегирования необходимо, чтобы политика домена Windows разрешала делегирование. Дополнительные сведения о настройке поддержки делегирования в Active Directory см. в разделе Включение делегированной проверки подлинности.

Примечание.

Если клиент проходит проверку подлинности во внешней службе с использованием имени пользователя и пароля, соответствующих учетной записи Windows во внутренней службе, внешняя служба может пройти проверку подлинности во внутренней службе, используя имя пользователя и пароль клиента. Это особенно мощная форма потока обработки удостоверений, поскольку передача имени пользователя и пароля внутренней службе позволяет этой службе выполнять олицетворение; однако в этом случае невозможно делегирование, так как не использует проверка подлинности Kerberos. Действие элементов управления делегированием службы каталогов Active Directory не распространяется на проверку подлинности имени пользователя и пароля.

Возможность делегирования как функция уровня олицетворения

Уровень олицетворения Служба может выполнять делегирование между процессами Служба может выполнять делегирование между компьютерами
Identification No No
Impersonation Да No
Delegation Да Да

В следующем примере кода показано, как использовать делегирование.

public class HelloService : IHelloService
{
    [OperationBehavior(Impersonation = ImpersonationOption.Required)]
    public string Hello(string message)
    {
        WindowsIdentity callerWindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity;
        if (callerWindowsIdentity == null)
        {
            throw new InvalidOperationException
             ("The caller cannot be mapped to a Windows identity.");
        }
        using (callerWindowsIdentity.Impersonate())
        {
            EndpointAddress backendServiceAddress = new EndpointAddress("http://localhost:8000/ChannelApp");
            // Any binding that performs Windows authentication of the client can be used.
            ChannelFactory<IHelloService> channelFactory = new ChannelFactory<IHelloService>(new NetTcpBinding(), backendServiceAddress);
            IHelloService channel = channelFactory.CreateChannel();
            return channel.Hello(message);
        }
    }
}
Public Class HelloService
    Implements IHelloService

    <OperationBehavior(Impersonation:=ImpersonationOption.Required)> _
    Public Function Hello(ByVal message As String) As String Implements IHelloService.Hello
        Dim callerWindowsIdentity As WindowsIdentity = ServiceSecurityContext.Current.WindowsIdentity
        If (callerWindowsIdentity Is Nothing) Then
            Throw New InvalidOperationException("The caller cannot be mapped to a Windows identity.")
        End If

        Dim backendServiceAddress As EndpointAddress = New EndpointAddress("http://localhost:8000/ChannelApp")
        ' Any binding that performs Windows authentication of the client can be used.
        Dim channelFactory As ChannelFactory(Of IHelloService) = _
          New ChannelFactory(Of IHelloService)(New NetTcpBinding(), backendServiceAddress)
        Dim channel As IHelloService = channelFactory.CreateChannel()
        Return channel.Hello(message)
    End Function
End Class

Настройка приложения для использования ограниченного делегирования

Для использования ограниченного делегирования необходимо предварительно настроить отправитель, получатель и контроллер домена. Ниже перечислены операции по включению ограниченного делегирования. Дополнительные сведения о различиях между делегированием и ограниченным делегированием см. в части раздела Расширения Kerberos Windows Server 2003 , посвященной ограниченному делегированию.

  1. На контроллере домена снимите флажок Учетная запись важна и не может быть делегирована для учетной записи, от имени которой выполняется клиентское приложение.

  2. На контроллере домена установите флажок Учетная запись доверена для делегирования для учетной записи, от имени которой выполняется клиентское приложение.

  3. На контроллере домена настройте компьютер промежуточного уровня, чтобы он был доверен для делегирования. Для этого установите параметр Доверять компьютеру делегирование .

  4. На контроллере домена настройте компьютер промежуточного уровня, чтобы он использовал ограниченное делегирование. Для этого установите параметр Этот компьютер доверенный для делегирования указанных служб .

Дополнительные инструкции по настройке ограниченного делегирования см. в разделе "Переход протокола Kerberos" и "Ограниченное делегирование".

См. также