Compartilhar via


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

A representação é uma técnica comum usada por serviços 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 ver um aplicativo de exemplo, confira Representação do 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 representação costuma ser usada como uma forma de verificar se um cliente está autorizado a executar uma determinada ação, enquanto a delegação é uma maneira de fluir recursos de representação, juntamente 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 é diferente do fluxo de identidade e, como transfere a capacidade de representar o cliente sem a posse da senha do cliente, é uma operação com muito mais privilégios do que o fluxo de identidade.

Tanto a representação quanto a delegação exigem que o cliente tenha uma identidade do Windows. Se um cliente não possuir uma identidade do Windows, a única opção disponível será 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 discute cenários comuns de implantação envolvendo representação e segurança SOAP e 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 da conta de serviço quando ela tenta representar, o tipo de representação usado e, possivelmente, a extensão de 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 no IIS 7.0, o cliente é executado na conta Network Service 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, confira 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 facilita isso, permitindo que o usuário especifique o requisito de representação no atributo OperationBehaviorAttribute. 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 método Hello 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 de enumeração ImpersonationOption ouImpersonationOption.RequiredImpersonationOption.Allowed, conforme mostrado no exemplo a seguir.

Observação

Quando um serviço tem credenciais superiores às do cliente remoto, as credenciais do serviço são usadas se a propriedade Impersonation 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 poderá 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 autenticação 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, confira Cenários sem suporte.

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

Às vezes, um chamador não precisa representar todo o método de serviço para funcionar, mas apenas uma 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 propriedade WindowsIdentity do ServiceSecurityContext para retornar uma instância da classe WindowsIdentity e chamando o método Impersonate antes de usar a instância.

Observação

Use a instrução Using do Visual Basic ou a instrução using de C# 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. Se não fizer isso, poderá formar a base para negação de serviço e elevação de ataques 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. Como mostra o código a seguir, defina a propriedade ImpersonateCallerForAllOperations como true. ServiceAuthorizationBehavior é recuperado das coleções de comportamentos da classe ServiceHost. Observe também que a propriedade Impersonation de OperationBehaviorAttribute aplicada a cada método também deve ser definida como 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/d O WCF representa o chamador
Permitido false O WCF não representa o chamador
Permitido true O WCF representa o chamador
NotAllowed false O WCF não representa o chamador
NotAllowed true Sem permissão. (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 configurando a propriedade AllowedImpersonationLevel da classe WindowsClientCredential, 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 comoAnonymous, Identification ou 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 obtido pelo serviço ao representar de um token armazenado em cache.

AllowedImpersonationLevel valor O serviço tem SeImpersonatePrivilege O serviço e o cliente são capazes de delegar Token armazenado em cache ImpersonationLevel
Anônima Sim n/d Representação
Anônima Não n/d Identificação
Identificação n/d n/d Identificação
Representação Sim n/d Representação
Representação Não n/d Identificação
Delegação Sim Sim Delegação
Delegação Sim No Representação
Delegação Não n/d 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 serviço 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 classes WindowsClientCredential e HttpDigestClientCredential.) A tabela a seguir fornece o nível de representaçã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/d Sim Sim Delegação
n/d Yes No Representação
n/a Não n/d 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 Yes n/d Representação
Sim Não n/d Identificação
Não n/d n/d Identificação

Mapeamento de 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, um serviço deve executar o Kerberos multi-leg (SSPI sem fallback NTLM) ou a autenticação direta Kerberos para o serviço de back-end usando 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 no nível da delegação exige que a política de domínio do Windows seja configurada para permitir a delegação. Para saber mais sobre como configurar o Active Directory para dar suporte à delegação, confira Habilitação da autenticação delegada.

Observação

Quando um cliente se autentica no serviço front-end usando um nome de usuário e uma senha que correspondem a uma conta do Windows no serviço de back-end, o serviço de front-end pode se autenticar 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 de nível de representaçã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 computadores
Identification No No
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 delegação restrita

Antes de 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, confira a parte das Extensões Kerberos do Windows Server 2003 que discute a delegação restrita.

  1. No controlador de domínio, desmarque a caixa de seleção 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 da conta na 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 Confiar mo computador para delegação.

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

Para obter instruções mais detalhadas sobre configuração da delegação restrita, confira Transição de protocolo Kerberos e delegação restrita.

Confira também