Compartilhar via


Delegação e representação com o WCF

Impersonação é uma técnica comum que os serviços usam para restringir o acesso do cliente aos recursos de um domínio de serviço. Os recursos de domínio de serviço podem ser recursos de computador, como arquivos locais (representação) ou um recurso em outro computador, como um compartilhamento de arquivos (delegação). Para obter um aplicativo de exemplo, consulte Como representar o cliente. Para obter um exemplo de como usar a representação, confira Como representar um cliente em um serviço.

Importante

Lembre-se de que, ao representar um cliente em um serviço, o serviço é executado com as credenciais do cliente, que podem ter privilégios mais altos do que o processo do servidor.

Visão geral

Normalmente, os clientes chamam um serviço para que o serviço execute alguma ação em nome do cliente. A representação permite que o serviço atue como o cliente durante a execução da ação. A delegação permite que um serviço front-end encaminhe a solicitação do cliente para um serviço de back-end de forma que o serviço de back-end também possa representar o cliente. A impersonação é mais comumente usada como uma forma de verificar se um cliente está autorizado a executar uma ação específica, enquanto a delegação é uma maneira de transmitir capacidades de impersonação, junto com a identidade do cliente, para um serviço de back-end. Delegação é um recurso de domínio do Windows que pode ser usado quando a autenticação baseada em Kerberos é executada. A delegação é distinta do fluxo de identidade e, como a delegação transfere a capacidade de representar o cliente sem a posse da senha do cliente, é uma operação com privilégios muito maior do que o fluxo de identidade.

A representação e a delegação exigem que o cliente tenha uma identidade do Windows. Se um cliente não possui uma identidade do Windows, a única opção disponível é fluir a identidade do cliente para o segundo serviço.

Noções básicas de representação

O WCF (Windows Communication Foundation) dá suporte à representação para diversas credenciais de cliente. Este tópico descreve o suporte ao modelo de serviço para representar o chamador durante a implementação de um método de serviço. Também são discutidos cenários comuns de implantação envolvendo impersonação (representação de identidade) e segurança SOAP, juntamente com as opções de WCF nesses cenários.

Este tópico se concentra na representação e na delegação no WCF ao usar a segurança SOAP. Você também pode usar representação e delegação com o WCF ao usar a segurança de transporte, conforme descrito em Usar representação com segurança de transporte.

Dois métodos

A segurança do WCF SOAP tem dois métodos distintos para executar a representação. O método usado depende da associação. Um deles é a representação de um token do Windows obtido da SSPI (Interface do Provedor de Suporte de Segurança) ou da autenticação Kerberos, que é armazenada em cache no serviço. A segunda é a representação de um token do Windows obtido de extensões Kerberos, chamadas coletivamente de S4U (Serviço para Usuário).

Representação de token armazenado em cache

Você pode executar a representação de token armazenado em cache com o seguinte:

Representação com base em S4U

Você pode executar a representação com base em S4U com o seguinte:

  • WSHttpBinding, WSDualHttpBinding e NetTcpBinding com uma credencial de cliente de certificado que o serviço pode mapear para uma conta válida do Windows.

  • Qualquer CustomBinding que use uma credencial de cliente do Windows com a propriedade requireCancellation definida como false.

  • Qualquer CustomBinding que use um nome de usuário ou uma credencial de cliente do Windows e uma conversa segura com a propriedade requireCancellation definida como false.

A extensão em que o serviço pode representar o cliente depende dos privilégios que a conta de serviço tem quando tenta representar, o tipo de representação usado e, possivelmente, a extensão da representação que o cliente permite.

Observação

Quando o cliente e o serviço estão em execução no mesmo computador e o cliente está em execução em uma conta do sistema (por exemplo, Local System ou Network Service), o cliente não pode ser representado quando uma sessão segura é estabelecida com tokens de Contexto de Segurança com estado. Normalmente, um aplicativo Windows Forms ou de console é executado na conta registrada no momento, para que essa conta possa ser representada por padrão. No entanto, quando o cliente é uma página ASP.NET e essa página é hospedada no IIS 6.0 ou IIS 7.0, o cliente é executado na Network Service conta por padrão. Todas as associações fornecidas pelo sistema que dão suporte a sessões seguras usam um SCT (token de contexto de segurança) sem estado por padrão. No entanto, se o cliente for uma página ASP.NET e sessões seguras com tokens SCT com estado forem usadas, o cliente não poderá ser representado. Para obter mais informações sobre como usar SCTs com estado em uma sessão segura, consulte Como criar um token de contexto de segurança para uma sessão segura.

Representação em um método de serviço: modelo declarativo

A maioria dos cenários de representação envolve a execução do método de serviço no contexto do chamador. O WCF fornece um recurso de representação que torna isso fácil de fazer, permitindo que o usuário especifique o requisito de representação no OperationBehaviorAttribute atributo. Por exemplo, no código a seguir, a infraestrutura do WCF representa o chamador antes de executar o método Hello. Qualquer tentativa de acessar recursos nativos dentro do Hello método terá êxito somente se a ACL (lista de controle de acesso) do recurso permitir os privilégios de acesso do chamador. Para habilitar a representação, defina a propriedade Impersonation como um dos valores da enumeração ImpersonationOption, ImpersonationOption.Required ou ImpersonationOption.Allowed, conforme mostrado no exemplo a seguir.

Observação

Quando um serviço tem credenciais mais altas que o cliente remoto, as credenciais do serviço são usadas se a Impersonation propriedade estiver definida como Allowed. Ou seja, se um usuário de baixo privilégio fornecer suas credenciais, um serviço com privilégios mais altos executará o método com as credenciais do serviço e poderá usar recursos que o usuário de baixo privilégio não seria capaz de usar.

[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

A infraestrutura do WCF só poderá representar o chamador se o chamador for autenticado com credenciais que podem ser mapeadas para uma conta de usuário do Windows. Se o serviço estiver configurado para autenticar usando uma credencial que não pode ser mapeada para uma conta do Windows, o método de serviço não será executado.

Observação

No Windows XP, a representação falhará se um SCT com estado for criado, resultando em um InvalidOperationException. Para obter mais informações, consulte Cenários sem suporte.

Representação em um método de serviço: modelo imperativo

Às vezes, um chamador não precisa simular todo o método de serviço para seu funcionamento, mas somente parte dele. Nesse caso, obtenha a identidade do Windows do chamador dentro do método de serviço e execute a representação de forma imperativa. Faça isso usando a WindowsIdentity propriedade do ServiceSecurityContext para retornar uma instância da WindowsIdentity classe e chamando o Impersonate método antes de usar a instância.

Observação

Certifique-se de usar a instrução Visual BasicUsing ou a instrução C# using para reverter automaticamente a ação de representação. Se você não usar a instrução, ou se usar uma linguagem de programação diferente de Visual Basic ou C#, não deixe de reverter o nível de representação. A falha em fazer isso pode formar a base para ataques de negação de serviço e elevação de privilégios.

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

Representação para todos os métodos de serviço

Em alguns casos, você deve executar todos os métodos de um serviço no contexto do chamador. Em vez de habilitar explicitamente esse recurso por método, use o ServiceAuthorizationBehavior. Conforme mostrado no código a seguir, defina a ImpersonateCallerForAllOperations propriedade como true. ServiceAuthorizationBehavior é recuperado das coleções de comportamentos da classe ServiceHost. Observe também que a propriedade Impersonation do OperationBehaviorAttribute aplicado a cada método também deve ser definida como ou Allowed ou 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

A tabela a seguir descreve o comportamento do WCF para todas as combinações possíveis de ImpersonationOption e ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Comportamento
Obrigatório Não disponível O WCF assume a identidade do chamador
Permitido falso O WCF não representa o chamador
Permitido verdadeiro O WCF assume a identidade do chamador
Não permitido falso O WCF não representa o chamador
Não permitido verdadeiro Não permitido. (Uma InvalidOperationException é lançada.)

Nível de representação obtido de credenciais do Windows e representação de token armazenado em cache

Em alguns cenários, o cliente tem controle parcial sobre o nível de representação que o serviço executa quando uma credencial de cliente do Windows é usada. Um cenário ocorre quando o cliente especifica um nível de representação anônimo. O outro ocorre ao executar a representação com um token armazenado em cache. Isso é feito definindo a AllowedImpersonationLevel propriedade da WindowsClientCredential classe, que é acessada como uma propriedade da classe genérica ChannelFactory<TChannel> .

Observação

Especificar um nível de representação do Anônimo faz com que o cliente faça logon no serviço anonimamente. Portanto, o serviço deve permitir logons anônimos, independentemente de a representação ser executada.

O cliente pode especificar o nível de representação como Anonymous, Identification, Impersonation ou Delegation. Somente um token no nível especificado é produzido, conforme mostrado no código a seguir.

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

A tabela a seguir especifica o nível de representação que o serviço obtém ao usar um token armazenado em cache para se representar.

Valor AllowedImpersonationLevel O serviço tem SeImpersonatePrivilege O serviço e o cliente são capazes de delegar Token armazenado em cache ImpersonationLevel
Anônimo Sim Não disponível Representação
Anônimo Não Não disponível Identificação
Identificação Não disponível Não disponível Identificação
Representação Sim Não disponível Representação
Representação Não Não disponível Identificação
Delegação Sim Sim Delegação
Delegação Sim Não Representação
Delegação Não Não disponível Identificação

Nível de representação obtido de credenciais de nome de usuário e representação de token armazenado em cache

Ao passar ao WCF seu nome de usuário e senha, um cliente permite que o WCF faça logon como esse usuário, o que equivale a definir a propriedade AllowedImpersonationLevel como Delegation. (A AllowedImpersonationLevel está disponível nas WindowsClientCredential e HttpDigestClientCredential classes.) A tabela a seguir fornece o nível de personificação obtido quando o serviço recebe credenciais de nome de usuário.

AllowedImpersonationLevel O serviço tem SeImpersonatePrivilege O serviço e o cliente são capazes de delegar Token armazenado em cache ImpersonationLevel
Não disponível Sim Sim Delegação
Não disponível Sim Não Representação
Não disponível Não Não disponível Identificação

Nível de representação obtido da representação com base em S4U

O serviço tem SeTcbPrivilege O serviço tem SeImpersonatePrivilege O serviço e o cliente são capazes de delegar Token armazenado em cache ImpersonationLevel
Sim Sim Não disponível Representação
Sim Não Não disponível Identificação
Não Não disponível Não disponível Identificação

Mapeando um certificado do cliente para uma conta do Windows

É possível que um cliente se autentique em um serviço usando um certificado e faça com que o serviço mapeie o cliente para uma conta existente por meio do Active Directory. O XML a seguir mostra como configurar o serviço para mapear o certificado.

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

O código a seguir mostra como configurar o serviço.

// 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;

Delegação

Para delegar a um serviço de back-end, é necessário que o serviço realize uma autenticação Kerberos multi-etapa (SSPI sem recurso ao NTLM) ou uma autenticação direta Kerberos no serviço de back-end, utilizando a identidade do Windows do cliente. Para delegar a um serviço de back-end, crie um ChannelFactory<TChannel> e um canal e, em seguida, comunique-se por meio do canal enquanto representa o cliente. Com essa forma de delegação, a distância na qual o serviço de back-end pode ser localizado a partir do serviço front-end depende do nível de representação alcançado pelo serviço front-end. Quando o nível de representação for Impersonation, os serviços front-end e back-end deverão estar em execução no mesmo computador. Quando o nível de representação for Delegation, os serviços front-end e back-end poderão estar em computadores separados ou no mesmo computador. Habilitar a representação em nível de delegação requer que a política de domínio do Windows seja configurada para permitir a delegação. Para obter mais informações sobre como configurar o Active Directory para suporte à delegação, consulte Habilitando a Autenticação Delegada.

Observação

Quando um cliente se autentica no serviço front-end usando um nome de usuário e senha que correspondem a uma conta do Windows no serviço de back-end, o serviço front-end pode autenticar-se no serviço de back-end reutilizando o nome de usuário e a senha do cliente. Essa é uma forma particularmente poderosa de fluxo de identidade, pois passar o nome de usuário e a senha para o serviço de back-end permite que o serviço execute a representação, mas não constitui delegação porque o Kerberos não é usado. Os controles do Active Directory na delegação não se aplicam à autenticação de nome de usuário e senha.

Capacidade de delegação como uma função do nível de imitação

Nível de representação O serviço pode executar a delegação entre processos O serviço pode executar a delegação entre diferentes máquinas
Identification Não Não
Impersonation Sim Não
Delegation Sim Sim

O exemplo de código a seguir demonstra como usar a delegação.

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

Como configurar um aplicativo para usar a delegação restrita

Antes de poder usar a delegação restrita, o remetente, o receptor e o controlador de domínio devem ser configurados para fazer isso. O procedimento a seguir lista as etapas que permitem a delegação restrita. Para obter detalhes sobre as diferenças entre delegação e delegação restrita, consulte a parte das Extensões Kerberos do Windows Server 2003 que discute a discussão restrita.

  1. No controlador de domínio, desmarque que a Conta é confidencial e não pode ser delegada para a conta na qual o aplicativo cliente está em execução.

  2. No controlador de domínio, marque a caixa de seleção Conta é confiável para delegação para a conta sob a qual o aplicativo cliente está em execução.

  3. No controlador de domínio, configure o computador de camada intermediária para que ele seja confiável para delegação, clicando na opção De confiança do computador para delegação .

  4. No controlador de domínio, configure o computador da camada intermediária para usar a delegação restrita, clicando na opção Confiar neste computador para delegação para serviços especificados .

Para obter instruções mais detalhadas sobre como configurar a delegação restrita, consulte Transição de Protocolo Kerberos e Delegação Restrita.

Consulte também