Compartir vía


Delegación y suplantación con WCF

Lasuplantación es una técnica habitual que utilizan los servicios para restringir el acceso de los clientes a los recursos de un dominio de servicio. Los recursos de dominio de servicio pueden ser recursos de equipo, como archivos locales (suplantación), o un recurso en otro equipo, como un recurso compartido de archivos (delegación). Para obtener una aplicación de ejemplo, consulte Impersonating the Client. Para obtener un ejemplo sobre el uso de la suplantación, consulte How to: Impersonate a Client on a Service.

Importante

Tenga en cuenta que al suplantar un cliente en un servicio, éste se ejecuta con las credenciales del cliente, que puede tener privilegios más altos que el proceso del servidor.

Información general

Normalmente, los clientes llaman a un servicio para que éste realice alguna acción en representación de cliente. La suplantación permite al servicio actuar como el cliente cuando realiza la acción. La delegación permite a un servicio front-end enviar la solicitud del cliente a un servicio back-end de modo que éste también puede suplantar al cliente. La suplantación se utiliza habitualmente como modo de comprobar si un cliente está autorizado para realizar una acción concreta, mientras que la delegación es una manera de hacer fluir las funciones de suplantación, junto con la identidad del cliente, a un servicio back-end. La delegación es una característica del dominio de Windows que puede usarse al realizar una autenticación basada en Kerberos. La delegación es diferente al flujo de identidad y, dado que la delegación transfiere la capacidad de suplantación del cliente sin poseer su contraseña, es una operación que disfruta de privilegios más elevados que el flujo de identidad.

Tanta la suplantación como la delegación requieren que el cliente posea una identidad de Windows. Si el cliente no posee una identidad de Windows, la única opción disponible es hacer fluir la identidad del cliente hasta el segundo servicio.

Fundamentos de la suplantación

Windows Communication Foundation (WCF) admite la suplantación para una variedad de credenciales de cliente. En este tema se describe la compatibilidad del modelo de servicio para suplantar al autor de la llamada durante la implementación de un método de servicio. También se tratan asuntos como los escenarios de implementación comunes que suponen la suplantación y la seguridad de SOAP, así como las opciones de WCF en estos escenarios.

Este tema se centra en la suplantación y delegación en WCF cuando se utiliza la seguridad de SOAP. También puede usar la suplantación y delegación con WCF al usar la seguridad de transporte, tal como se describe en Utilización de la suplantación con la seguridad de transporte.

Dos métodos

La seguridad de SOAP de WCF tiene dos métodos distintos para realizar la suplantación. El método utilizado depende del enlace. El primero es la suplantación de un token de Windows obtenido desde la interfaz de proveedor de compatibilidad para seguridad (SSPI) o la autenticación de Kerberos, que se almacena en la memoria caché en el servicio. El segundo es la suplantación de un token de Windows obtenido a partir de las extensiones de Kerberos, denominado en su conjunto servicio para usuario (S4U).

Suplantación del token almacenado en caché

Puede realizar la suplantación del token almacenado en caché con lo siguiente:

Suplantación basada en S4U

Puede realizar la suplantación basada en S4U con lo siguiente:

  • WSHttpBinding, WSDualHttpBindingy NetTcpBinding con una credencial de certificado de cliente que el servicio puede asignar a una cuenta de Windows válida.

  • Cualquier CustomBinding que utiliza una credencial de cliente de Windows con la propiedad requireCancellation definida en false.

  • Cualquier CustomBinding que utiliza un nombre de usuario o credencial de cliente de Windows y una conversación segura con la propiedad requireCancellation establecida en false.

Hasta qué punto el servicio puede suplantar al cliente depende de los privilegios que la cuenta de servicio contiene al intentar suplantar, el tipo de suplantación utilizado y posiblemente hasta qué punto el cliente permite la suplantación.

Nota

Cuando el cliente y el servicio se están ejecutando en el mismo equipo y el cliente se está ejecutando bajo una cuenta del sistema (por ejemplo, Local System o Network Service), no se puede suplantar el cliente cuando una sesión segura se establece con tokens de contexto de seguridad con estado. Una aplicación Windows Form o de consola se ejecutan normalmente con la cuenta con la que haya iniciado la sesión, de manera que la cuenta pueda suplantarse de manera predeterminada. No obstante, cuando el cliente es una página ASP.NET que se hospeda en ISS 6.0 o ISS 7.0, el cliente se ejecuta, de manera predeterminada, en la cuenta Network Service. Todos los enlaces proporcionados por el sistema que admiten sesiones seguras utilizan de forma predeterminada un token de contexto de seguridad sin estado (SCT). Sin embargo, si el cliente es una página ASP.NET y se usan sesiones seguras con SCT con estado, no se puede suplantar al cliente. Para más información sobre el uso de SCT con estado en una sesión segura, consulte Creación de un token de seguridad para una sesión segura.

Suplantación en un método de servicio: modelo declarativo

La mayoría de los escenarios de suplantación implican la ejecución del método de servicio en el contexto del autor de llamada. WCF proporciona una característica de suplantación que lo facilita al permitir que el usuario especifique el requisito de suplantación en el atributo OperationBehaviorAttribute. Por ejemplo, en el código siguiente, la infraestructura de WFC suplanta al autor de la llamada antes de ejecutar el método Hello. Cualquier intento para tener acceso a los recursos nativos dentro del método Hello solo tiene éxito si la lista de control de acceso (ACL) del recurso permite privilegios de acceso al autor de la llamada. Para habilitar la suplantación, establezca la propiedad Impersonation en uno de los valores de enumeración ImpersonationOption , ImpersonationOption.Required o ImpersonationOption.Allowed, tal y como se muestra en el ejemplo siguiente.

Nota

Cuando un servicio tiene las credenciales más altas que el cliente remoto, se utilizan las credenciales del servicio si la propiedad Impersonation está establecida en Allowed. Es decir, si un usuario con pocos privilegios proporciona sus credenciales, un servicio con más privilegios ejecuta el método con las credenciales del servicio y puede utilizar los recursos que el usuario con pocos privilegios no podría utilizar.

[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

La infraestructura de WCF solo puede suplantar al autor de la llamada si este se autentica con credenciales que pueden estar asignadas a una cuenta de usuario de Windows. Si el servicio se configura para autenticar utilizando una credencial que no puede estar asignada a una cuenta de Windows, no se ejecutará el método de servicio.

Nota

En Windows XP, se produce un error en la suplantación si se crea un SCT con estado dando como resultado InvalidOperationException. Para más información, consulte Escenarios no admitidos.

Suplantación en un método de servicio: modelo imperativo

En ocasiones, un autor de la llamada no necesita suplantar todo el método de servicio para funcionar, sino solo una parte de él. En este caso, obtenga la identidad de Windows del autor de la llamada dentro del método de servicio y realice la suplantación inmediatamente. Haga esto utilizando la propiedad WindowsIdentity de ServiceSecurityContext para devolver una instancia de la clase WindowsIdentity y llamando al método Impersonate antes de utilizar la instancia.

Nota

Asegúrese de usar la instrucción Using de Visual Basic o la instrucción using de C# para invertir automáticamente la acción de suplantación. Si no utiliza la instrucción o si utiliza un lenguaje de programación distinto de Visual Basic o C#, asegúrese de invertir el nivel de suplantación. El no hacerlo puede ser la base de la denegación de servicio y aumentar los ataques contra los privilegios.

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

Suplantación para todos los métodos de servicio

En algunos casos, debe realizar todos los métodos de un servicio en el contexto del autor de la llamada. En lugar de habilitar explícitamente esta característica por método, use la clase ServiceAuthorizationBehavior. Tal y como se muestra en el código siguiente, defina la propiedad ImpersonateCallerForAllOperations en true. ServiceAuthorizationBehavior se recupera de las colecciones de comportamientos de la clase ServiceHost . Además, tenga en cuenta que la propiedad Impersonation de OperationBehaviorAttribute que se aplica a cada método debe definirse también en Allowed o 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

En la tabla siguiente, se describe el comportamiento de WCF para todas las combinaciones posibles de ImpersonationOption y ImpersonateCallerForAllServiceOperations.

ImpersonationOption ImpersonateCallerForAllServiceOperations Comportamiento
Obligatorio N/D WCF suplanta al autor de la llamada
Permitida false WCF no suplanta al autor de la llamada
Permitida true WCF suplanta al autor de la llamada
No permitidos false WCF no suplanta al autor de la llamada
No permitidos true No permitido. (Se produce una excepción InvalidOperationException .)

Nivel de suplantación obtenido de las credenciales de Windows y la suplantación de tokens almacenados en caché

En algunos escenarios, el cliente tiene el control parcial sobre el nivel de suplantación que el servicio realiza cuando se utiliza una credencial de cliente de Windows. Se produce un escenario cuando el cliente especifica un nivel de suplantación anónimo. El otro se produce cuando se realiza la suplantación con un token en memoria caché. Esto se realiza estableciendo la propiedad AllowedImpersonationLevel de la clase WindowsClientCredential , a la que se obtiene acceso como una propiedad de la clase ChannelFactory<TChannel> genérica.

Nota

Especificar un nivel de suplantación de anónimo hace que el cliente inicie sesión anónimamente en el servicio. Por lo tanto, el servicio debe permitir inicios de sesión anónimos, sin tener en cuenta si se realiza la suplantación.

El cliente puede especificar el nivel de suplantación como Anonymous, Identification, Impersonationo Delegation. Se genera solo un token en el nivel especificado, tal y como se muestra en el código siguiente.

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

La tabla siguiente especifica el nivel de suplantación que el servicio obtiene al suplantar un token almacenado en memoria caché.

Valor de AllowedImpersonationLevel El servicio tiene SeImpersonatePrivilege El servicio y el cliente tienen capacidad de delegación ImpersonationLevel
Anónimas N/D Suplantación
Anónimas No N/D Identificación
Identificación N/D N/D Identificación
Suplantación N/D Suplantación
Suplantación No N/D Identificación
Delegación Delegación
Delegación No Suplantación
Delegación No N/D Identificación

Nivel de suplantación obtenido a partir de las credenciales de nombre de usuario y suplantación de token almacenado en caché

Al pasar su nombre de usuario y contraseña al servicio, un cliente permite que WCF inicie sesión como ese usuario, lo que es equivalente a establecer la propiedad AllowedImpersonationLevel en Delegation. (AllowedImpersonationLevel está disponible en las clases WindowsClientCredential y HttpDigestClientCredential). En la tabla siguiente, se proporciona el nivel de suplantación obtenido cuando el servicio recibe las credenciales del nombre de usuario.

AllowedImpersonationLevel El servicio tiene SeImpersonatePrivilege El servicio y el cliente tienen capacidad de delegación ImpersonationLevel
N/D Delegación
N/D No Suplantación
N/D No N/D Identificación

Nivel de suplantación obtenido de la suplantación basada en S4U

El servicio tiene SeTcbPrivilege El servicio tiene SeImpersonatePrivilege El servicio y el cliente tienen capacidad de delegación ImpersonationLevel
N/D Suplantación
No N/D Identificación
No n/d N/D Identificación

Asignación de un certificado de cliente a una cuenta de Windows

Un cliente se puede autenticar en un servicio mediante un certificado y hacer que el servicio asigne el cliente a una cuenta existente a través de Active Directory. En el XML siguiente, se muestra cómo configurar el servicio para asignar el certificado.

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

En el código siguiente, se muestra cómo configurar el servicio.

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

Delegación

Para delegar en un servicio back-end, un servicio debe realizar la multibifurcación Kerberos (SSPI sin reserva NTLM), o la autenticación directa de Kerberos en un servicio back-end que utilice la identidad de Windows del cliente. Para delegar en un servicio back-end, cree una clase ChannelFactory<TChannel> y un canal, y después establezca la comunicación a través del canal al tiempo que suplanta al cliente. Con este tipo de delegación, la distancia a la que puede ubicarse el servicio back-end del servicio front-end depende del nivel de suplantación logrado por éste último. Cuando el nivel de suplantación es Impersonation, los servicios front-end y back-end deben ejecutarse en el mismo equipo. Cuando el nivel de suplantación es Delegation, los servicios front-end y back-end pueden ejecutarse en equipos distintos o en el mismo equipo. Para habilitar la suplantación en el nivel de delegación es necesario configurar la directiva de dominio de Windows de modo que permita la delegación. Para obtener más información sobre la configuración de Active Directory para admitir la delegación, consulte Enabling Delegated Authentication (Habilitar la autenticación delegada).

Nota

Cuando un cliente se autentica en el servicio front-end mediante un nombre de usuario y una contraseña que se corresponden con una cuenta de Windows del servicio back-end, el servicio front-end puede autenticarse en el servicio back-end volviendo a utilizar el nombre de usuario y la contraseña del cliente. Este es un modo especialmente eficaz de flujo de identidad ya que pasar el nombre de usuario y la contraseña al servicio back-end permite a este último realizar la suplantación, pero no constituye una delegación ya que no se usa Kerberos. Active Directory controla la delegación pero no aplica la autenticación del nombre de usuario y la contraseña.

Capacidad de delegación como función del nivel de suplantación

Nivel de suplantación El servicio puede realizar una delegación entre procesos El servicio puede realizar una delegación entre equipos
Identification No No
Impersonation No
Delegation

En el siguiente ejemplo de código se muestra cómo utilizar la delegación.

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

Cómo: Configurar una aplicación para utilizar la delegación restringida

Antes de poder utilizar la delegación restringida, debe configurarse el emisor, el receptor y el controlador de dominio para poder utilizarla. La siguiente lista de procedimiento enumera los pasos para habilitar la delegación restringida. Para obtener más información sobre las diferencias entre la delegación y la delegación restringida, consulte la parte de Windows Server 2003 Kerberos Extensions (Extensiones Kerberos de Windows Server 2003) en la que se explica la delegación restringida.

  1. En el controlador de dominio, desactive la casilla La cuenta es importante y no se puede delegar de la cuenta con la que se está ejecutando la aplicación cliente.

  2. En el controlador de dominio, active la casilla La cuenta es de confianza para la delegación para la cuenta con la que se está ejecutando la aplicación cliente.

  3. En el controlador de domino, configure el equipo de nivel medio de modo que sea de confianza para la delegación haciendo clic en la opción Equipo de confianza para la delegación .

  4. En el controlador de domino, configure el equipo de nivel medio para utilizar la delegación restringida haciendo clic en la opción Confiar en este equipo solo para delegación en servicios especificados .

Para instrucciones detalladas sobre la configuración de la delegación restringida, consulte Transición de protocolos y delegación restringida de Kerberos.

Consulte también