Compartir a través de


Delegación y suplantación con WCF

La suplantació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, vea Impersonating the Client. Para consultar un ejemplo sobre el uso de la suplantación, vea Cómo suplantar a un cliente en un servicio.

ms730088.Important(es-es,VS.100).gif Nota:
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 diversas credenciales del 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 utilizar la suplantación y delegación con WCF al utilizar la seguridad del transporte, tal y 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, WSDualHttpBinding y 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.

ms730088.note(es-es,VS.100).gifNota:
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. Un formulario de Windows o la aplicación 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. Sin embargo, cuando el cliente es una página ASP.NET y se hospeda en IIS 6.0 o IIS 7.0, el cliente se ejecutará a continuación con la cuenta Network Service de manera predeterminada. 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 utilizan las sesiones seguras con SCT con estado, no se puede suplantar el cliente. Para obtener más información sobre utilizar SCT con estado en una sesión segura, vea Cómo: Crear un token de contexto 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 la llamada. WCF proporciona una característica de suplantación que facilita esta acción permitiendo al usuario especificar el requisito de suplantación en el atributo OperationBehaviorAttribute. Por ejemplo, en el código siguiente, la infraestructura WCF 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, System.ServiceModel.ImpersonationOption.Required o System.ServiceModel.ImpersonationOption.Allowed, tal y como se muestra en el ejemplo siguiente.

ms730088.note(es-es,VS.100).gifNota:
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()>  _
    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 
[ServiceContract]
public interface IHelloContract
{
    [OperationContract]
    string Hello(string message);
}

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

La infraestructura de WCF solo puede suplantar al autor de la llamada si éste 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.

ms730088.note(es-es,VS.100).gifNota:
En Windows XP, se produce un error en la suplantación si se crea un SCT con estado dando como resultado InvalidOperationException. Para obtener más información, vea 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.

ms730088.note(es-es,VS.100).gifNota:
Asegúrese de utilizar la instrucción Visual Basic o la instrucción Using de C# using 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
    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 
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";
    }
}

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.
Dim MyServiceAuthoriationBehavior As ServiceAuthorizationBehavior 
MyServiceAuthoriationBehavior= serviceHost.Description.Behaviors.Find _
(Of ServiceAuthorizationBehavior)()
MyServiceAuthoriationBehavior.ImpersonateCallerForAllOperations = True
// Code to create a ServiceHost not shown.
ServiceAuthorizationBehavior MyServiceAuthoriationBehavior = 
    serviceHost.Description.Behaviors.Find<ServiceAuthorizationBehavior>();
MyServiceAuthoriationBehavior.ImpersonateCallerForAllOperations = true;

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

ImpersonationOption ImpersonateCallerForAllServiceOperations Comportamiento

Required

n/a

WCF suplanta al autor de la llamada

Permitido

false

WCF no suplanta al autor de la llamada

Permitido

true

WCF suplanta al autor de la llamada

NotAllowed

false

WCF no suplanta al autor de la llamada

NotAllowed

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 genérica.

ms730088.note(es-es,VS.100).gifNota:
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, Impersonation o Delegation. Se genera solo un token en el nivel especificado, tal y como se muestra en el código siguiente.

Dim cf As ChannelFactory(Of IEcho) = New ChannelFactory(Of IEcho)("EchoEndpoint")
cf.Credentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Impersonation
ChannelFactory<IEcho> cf = new ChannelFactory<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 de token almacenado en memoria caché

Anónimo

n/a

Suplantación

Anónimo

No

n/a

Identificación

Identificación

n/a

n/a

Identificación

Suplantación

n/a

Suplantación

Suplantación

No

n/a

Identificación

Delegación

Delegación

Delegación

No

Suplantación

Delegación

No

n/a

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.) La tabla siguiente 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 de token almacenado en memoria caché

n/a

Delegación

n/a

No

Suplantación

n/a

No

n/a

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 de token almacenado en memoria caché

n/a

Suplantación

No

n/a

Identificación

No

n/a

n/a

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("https://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 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 acerca de la configuración de Active Directory para admitir la delegación, vea Habilitar la autenticación delegada.

ms730088.note(es-es,VS.100).gifNota:
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
    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("https://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
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("https://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);
        }
    }
}

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 acerca de las diferencias entre la delegación y la delegación restringida, vea la parte de Extensiones Kerberos de Windows Server 2003 en la que se explica la delegación.

  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 obtener instrucciones detalladas acerca de la configuración de la delegación restringida, vea los siguientes temas en MSDN:

Vea también

Tareas

Impersonating the Client
Cómo suplantar a un cliente en un servicio

Referencia

OperationBehaviorAttribute
Impersonation
ImpersonationOption
WindowsIdentity
ServiceSecurityContext
WindowsIdentity
ServiceAuthorizationBehavior
ImpersonateCallerForAllOperations
ServiceHost
AllowedImpersonationLevel
WindowsClientCredential
ChannelFactory
Identification

Conceptos

Utilización de la suplantación con la seguridad de transporte
Herramienta de utilidad de metadatos de ServiceModel (Svcutil.exe)