Delegação e representação com WCF

A representaçã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 do domínio de serviço podem ser recursos de máquina, como arquivos locais (representação), ou um recurso em outra máquina, como um compartilhamento de arquivos (delegação). Para um aplicativo de exemplo, consulte Representando o cliente. Para obter um exemplo de como usar a representação, consulte 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.

Descriçã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 back-end de tal forma que o serviço back-end também possa representar o cliente. A representação é mais comumente usada como uma forma de verificar se um cliente está autorizado a executar uma determinada ação, enquanto a delegação é uma forma de fluir os recursos de representação, juntamente com a identidade do cliente, para um serviço de back-end. A 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 se passar pelo cliente sem a posse da senha do cliente, é uma operação privilegiada muito maior 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 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 Windows Communication Foundation (WCF) oferece suporte à representação de uma variedade de 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 de implantação comuns envolvendo representação e segurança SOAP e opções WCF nesses cenários.

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

Dois métodos

A segurança WCF SOAP tem dois métodos distintos para executar a representação. O método utilizado depende da ligação. Uma delas é a representação de um token do Windows obtido da SSPI (Security Support Provider Interface) ou da autenticação Kerberos, que é armazenada em cache no serviço. O segundo é a representação de um token do Windows obtido das extensões Kerberos, coletivamente chamado de Service-for-User (S4U).

Representação de token em cache

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

Representação baseada em S4U

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

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

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

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

A medida em que o serviço pode personificar o cliente depende dos privilégios que a conta de serviço detém quando tenta a falsificação de identidade, do tipo de representação usado e, possivelmente, da extensão da personificação que o cliente permite.

Nota

Quando o cliente e o serviço estão sendo executados no mesmo computador e o cliente está sendo executado 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 monitoração de estado. Um aplicativo de console ou formulário do Windows normalmente é executado na conta conectada no momento, para que a conta possa ser representada por padrão. No entanto, quando o cliente é uma página ASP.NET e essa página está hospedada no IIS 6.0 ou IIS 7.0, o cliente é executado sob a Network Service conta por padrão. Todas as associações fornecidas pelo sistema que suportam sessões seguras usam um token de contexto de segurança (SCT) sem estado por padrão. No entanto, se o cliente for uma página ASP.NET e sessões seguras com SCTs com monitoração de estado forem usadas, o cliente não poderá ser representado. Para obter mais informações sobre como usar SCTs com monitoração de 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 facilita isso, permitindo que o usuário especifique o requisito de representação no OperationBehaviorAttribute atributo. Por exemplo, no código a seguir, a infraestrutura WCF representa o chamador antes de executar o Hello método. Qualquer tentativa de acessar recursos nativos dentro do Hello método será bem-sucedida somente se a lista de controle de acesso (ACL) do recurso permitir os privilégios de acesso do chamador. Para habilitar a ImpersonationOption representação, defina a Impersonation propriedade como um dos valores de enumeração, ou ImpersonationOption.RequiredImpersonationOption.Allowed, conforme mostrado no exemplo a seguir.

Nota

Quando um serviço tem credenciais mais altas do 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 com privilégios baixos 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, de outra forma, o usuário com privilégios baixos não poderia 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 WCF pode representar o chamador somente se ele estiver 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.

Nota

No Windows XP, a representação falhará se um SCT com estado for criado, resultando em um InvalidOperationExceptionarquivo . 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 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 imperativamente a representação. Faça isso usando a WindowsIdentity propriedade do ServiceSecurityContext para retornar uma instância da classe e chamando o Impersonate método antes de WindowsIdentity usar a instância.

Nota

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 você usar uma linguagem de programação diferente de Visual Basic ou C#, certifique-se de reverter o nível de representação. Não fazer isso pode formar a base para a negação de serviço e elevação de ataques de privilégio.

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. O ServiceAuthorizationBehavior é recuperado das coleções de comportamentos da ServiceHost classe. Observe também que a ImpersonationOperationBehaviorAttribute propriedade do aplicado a cada método também deve ser definida como ou AllowedRequired.

// 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
Necessário n/d WCF personifica o chamador
Permitido false O WCF não se faz passar pelo chamador
Permitido verdadeiro WCF personifica o chamador
Não permitido false O WCF não se faz passar pelo chamador
Não permitido verdadeiro Não permitido. (Um InvalidOperationException é jogado.)

Nível de representação obtido a partir de credenciais do Windows e representação de token 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 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 AllowedImpersonationLevelWindowsClientCredential propriedade da classe, que é acessada como uma propriedade da classe genérica ChannelFactory<TChannel> .

Nota

Especificar um nível de representação de Anonymous faz com que o cliente faça logon no serviço anonimamente. O serviço deve, portanto, permitir logons anônimos, independentemente de a falsificação de identidade ser realizada.

O cliente pode especificar o nível de representação como Anonymous, Identification, Impersonationou Delegation. Apenas 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 representar a partir de um token armazenado em cache.

AllowedImpersonationLevel valor Serviço tem SeImpersonatePrivilege Serviço e cliente são capazes de delegação Token armazenado em cache ImpersonationLevel
Anónimo Sim n/d Falsificação de identidade
Anónimo No n/d Identificação
Identificação n/d n/d Identificação
Falsificação de identidade Sim n/d Falsificação de identidade
Falsificação de identidade No n/d Identificação
Delegação Sim Sim Delegação
Delegação Sim No Falsificação de identidade
Delegação No n/d Identificação

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

Ao passar o 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 AllowedImpersonationLevel propriedade como Delegation. (O AllowedImpersonationLevel está disponível nas WindowsClientCredential e HttpDigestClientCredential aulas.) A tabela a seguir fornece o nível de representação obtido quando o serviço recebe credenciais de nome de usuário.

AllowedImpersonationLevel Serviço tem SeImpersonatePrivilege Serviço e cliente são capazes de delegação Token armazenado em cache ImpersonationLevel
n/d Sim Sim Delegação
n/d Sim No Falsificação de identidade
n/d No n/d Identificação

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

Serviço tem SeTcbPrivilege Serviço tem SeImpersonatePrivilege Serviço e cliente são capazes de delegação Token armazenado em cache ImpersonationLevel
Sim Sim n/d Falsificação de identidade
Sim No n/d Identificação
No n/d n/d Identificação

Mapeando um certificado de cliente para uma conta do Windows

É possível que um cliente se autentique em um serviço usando um certificado e que o serviço mapeie o cliente para uma conta existente por meio do Ative 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 back-end, um serviço deve executar Kerberos multi-leg (SSPI sem fallback NTLM) ou autenticação direta Kerberos para o serviço back-end usando a identidade Windows do cliente. Para delegar a um serviço de back-end, crie um ChannelFactory<TChannel> e um canal e, em seguida, comunique através do canal enquanto se faz passar pelo cliente. Com essa forma de delegação, a distância na qual o serviço back-end pode ser localizado 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 é Impersonation, os serviços front-end e back-end devem estar em execução na mesma máquina. Quando o nível de representação é Delegation, os serviços front-end e back-end podem estar em máquinas separadas ou na mesma máquina. Habilitar a representação no nível de delegação requer que a diretiva de domínio do Windows seja configurada para permitir a delegação. Para obter mais informações sobre como configurar o Ative Directory para suporte de delegação, consulte Habilitando a autenticação delegada.

Nota

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 back-end, o serviço front-end pode autenticar no serviço back-end reutilizando o nome de usuário e a senha do cliente. Essa é uma forma particularmente poderosa de fluxo de identidade, porque passar nome de usuário e senha para o serviço back-end permite que o serviço back-end execute a representação, mas não constitui delegação porque Kerberos não é usado. Os controles do Ative Directory na delegação não se aplicam à autenticação de nome de usuário e senha.

Capacidade de delegação em função do 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 máquinas
Identification No No
Impersonation Sim No
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 poder usar a delegação restrita, o remetente, o recetor e o controlador de domínio devem ser configurados para 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 a caixa de seleção Conta é confidencial e não pode ser delegada para a conta na qual o aplicativo cliente está sendo executado.

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

  3. No controlador de domínio, configure o computador de camada intermediária para que seja confiável para delegação, clicando na opção Confiar no 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 somente a serviços especificados.

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

Consulte também