Compartir a través de


Programación de la seguridad de WCF

En este tema se describen las tareas de programación fundamentales que se usan para crear una aplicación segura de Windows Communication Foundation (WCF). En este tema solo se tratan la autenticación, la confidencialidad y la integridad, conocidas colectivamente como seguridad de transferencia. Este tema no cubre la autorización (el control del acceso a los recursos o servicios); para obtener información sobre la autorización, consulte Autorización.

Nota:

Para obtener una valiosa introducción a los conceptos de seguridad, especialmente en lo que respecta a WCF, consulte el conjunto de tutoriales de patrones y prácticas en MSDN en Escenarios, Patrones e Instrucciones de implementación para mejoras de servicios web (WSE) 3.0.

La programación de la seguridad de WCF se basa en tres pasos que establecen lo siguiente: el modo de seguridad, un tipo de credencial de cliente y los valores de credenciales. Puede realizar estos pasos a través del código o la configuración.

Establecer el modo de seguridad

A continuación se explican los pasos generales para programar con el modo de seguridad en WCF:

  1. Seleccione uno de los enlaces predefinidos adecuados para los requisitos de la aplicación. Para obtener una lista de las opciones de enlaces, consulte Enlaces que proporciona el sistema. De forma predeterminada, casi todos los enlaces tienen habilitada la seguridad. La única excepción es la clase BasicHttpBinding (utilizando configuración, el <basicHttpBinding>).

    La vinculación que seleccione determina el transporte. Por ejemplo, WSHttpBinding usa HTTP como transporte; NetTcpBinding usa TCP.

  2. Seleccione uno de los modos de seguridad para el enlace. Tenga en cuenta que la vinculación que seleccione determina las opciones de modo disponibles. Por ejemplo, el WSDualHttpBinding no permite la seguridad en el transporte (no es una opción). Del mismo modo, ni el MsmqIntegrationBinding ni el NetNamedPipeBinding permiten la seguridad del mensaje.

    Dispone de tres opciones:

    1. Transport

      La seguridad de transporte depende del mecanismo que usa el enlace seleccionado. Por ejemplo, si está utilizando WSHttpBinding, el mecanismo de seguridad es la Capa de Sockets Seguros (SSL) (que también es el mecanismo para el protocolo HTTPS). Por lo general, la principal ventaja de la seguridad de transporte es que ofrece un buen rendimiento independientemente del transporte que use. Sin embargo, tiene dos limitaciones: la primera es que el mecanismo de transporte dicta el tipo de credencial que se usa para autenticar a un usuario. Este es un inconveniente solo si un servicio necesita interoperar con otros servicios que exigen diferentes tipos de credenciales. El segundo es que, dado que la seguridad no se aplica en el nivel de mensaje, la seguridad se implementa de forma de salto a salto en lugar de un extremo a otro. Esta última limitación es un problema solo si la ruta de acceso del mensaje entre el cliente y el servicio incluye intermediarios. Para obtener más información sobre el transporte que se va a usar, consulte Elección de un transporte. Para obtener más información sobre el uso de la seguridad de transporte, consulte Introducción a la seguridad de transporte.

    2. Message

      La seguridad del mensaje significa que cada mensaje incluye los encabezados y datos necesarios para mantener el mensaje seguro. Dado que la composición de los encabezados varía, puede incluir cualquier número de credenciales. Esto se convierte en un factor si está interoperando con otros servicios que exigen un tipo de credencial específico que un mecanismo de transporte no puede proporcionar, o si el mensaje debe usarse con más de un servicio, donde cada servicio exige un tipo de credencial diferente.

      Para obtener más información, consulte Seguridad de mensajes.

    3. TransportWithMessageCredential

      Esta opción usa la capa de transporte para proteger la transferencia de mensajes, mientras que cada mensaje incluye las credenciales enriquecidas que necesitan otros servicios. Esto combina la ventaja de rendimiento de la seguridad de transporte con la ventaja de credenciales enriquecidas de seguridad de mensajes. Esto está disponible con los siguientes enlaces: BasicHttpBinding, WSFederationHttpBinding, NetPeerTcpBindingy WSHttpBinding.

  3. Si decide usar la seguridad de transporte para HTTP (es decir, HTTPS), también debe configurar el host con un certificado SSL y habilitar SSL en un puerto. Para obtener más información, consulte Seguridad de transporte HTTP.

  4. Si usa WSHttpBinding y no es necesario establecer una sesión segura, establezca la propiedad EstablishSecurityContext en false.

    Una sesión segura se produce cuando un cliente y un servicio crean un canal mediante una clave simétrica (tanto el cliente como el servidor usan la misma clave para la longitud de una conversación, hasta que se cierra el cuadro de diálogo).

Establecimiento del tipo de credencial de cliente

Seleccione un tipo de credencial de cliente según corresponda. Para obtener más información, vea Seleccionar un tipo de credencial. Están disponibles los siguientes tipos de credenciales de cliente:

  • Windows

  • Certificate

  • Digest

  • Basic

  • UserName

  • NTLM

  • IssuedToken

En función de cómo establezca el modo, debe establecer el tipo de credencial. Por ejemplo, si ha seleccionado wsHttpBindingy ha establecido el modo en "Message", también puede establecer el clientCredentialType atributo del elemento Message en uno de los valores siguientes: None, Windows, UserName, Certificatey IssuedToken, como se muestra en el ejemplo de configuración siguiente.

<system.serviceModel>  
<bindings>  
  <wsHttpBinding>  
    <binding name="myBinding">  
      <security mode="Message"/>  
      <message clientCredentialType="Windows"/>  
    </binding>
  </wsHttpBinding>
</bindings>  
</system.serviceModel>  

O en el código:

WSHttpBinding b = new WSHttpBinding();
b.Name = "myBinding";
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType=MessageCredentialType.Windows;
Dim b As New WSHttpBinding()
b.Name = "myBinding"
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows

Establecimiento de valores de credenciales de servicio

Una vez que seleccione un tipo de credencial de cliente, debe establecer las credenciales reales para que use el servicio y el cliente. En el servicio, las credenciales se establecen mediante la ServiceCredentials clase y se devuelven mediante la Credentials propiedad de la ServiceHostBase clase . El enlace en uso implica el tipo de credencial de servicio, el modo de seguridad elegido y el tipo de la credencial de cliente. El código siguiente establece un certificado para una credencial de servicio.

// Create the binding for an endpoint.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;

// Create the ServiceHost for a calculator.
Uri baseUri = new Uri("net.tcp://MachineName/tcpBase");
Uri[] baseAddresses = new Uri[] { baseUri };
ServiceHost sh = new ServiceHost(typeof(Calculator), baseAddresses);

// Add an endpoint using the binding and a new address.
Type c = typeof(ICalculator);
sh.AddServiceEndpoint(c, b, "MyEndpoint");

// Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate(
    StoreLocation.LocalMachine,
    StoreName.My,
    X509FindType.FindBySubjectName,
    "client.com");
try
{
    sh.Open();
    Console.WriteLine("Listening....");
    Console.ReadLine();
    sh.Close();
}
catch (CommunicationException ce)
{
    Console.WriteLine($"A communication error occurred: {ce.Message}");
    Console.WriteLine();
}
catch (System.Exception exc)
{
    Console.WriteLine($"An unforeseen error occurred: {exc.Message}");
    Console.ReadLine();
}
' Create the binding for an endpoint.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message

' Create the ServiceHost for a calculator.
Dim baseUri As New Uri("net.tcp://MachineName/tcpBase")
Dim baseAddresses() As Uri = {baseUri}
Dim sh As New ServiceHost(GetType(Calculator), baseAddresses)

' Add an endpoint using the binding and a new address.
Dim c As Type = GetType(ICalculator)
sh.AddServiceEndpoint(c, b, "MyEndpoint")

' Set a certificate as the credential for the service.
sh.Credentials.ServiceCertificate.SetCertificate( _
                StoreLocation.LocalMachine, _
                StoreName.My, _
                X509FindType.FindBySubjectName, _
                "contoso.com")
Try
    sh.Open()
    Console.WriteLine("Listening....")
    Console.ReadLine()
    sh.Close()
Catch ce As CommunicationException
    Console.WriteLine("A communication error occurred: {0}", ce.Message)
    Console.WriteLine()
Catch exc As System.Exception
    Console.WriteLine("An unforeseen error occurred: {0}", exc.Message)
    Console.ReadLine()
End Try

Establecer valores de credenciales de cliente

En el cliente, establezca los valores de credenciales de cliente utilizando la clase ClientCredentials y devuelta por la propiedad ClientCredentials de la clase ClientBase<TChannel>. El código siguiente establece un certificado como una credencial en un cliente mediante el protocolo TCP.

// Create a NetTcpBinding and set its security properties. The
// security mode is Message, and the client must be authenticated with
// Windows. Therefore the client must be on the same Windows ___domain.
NetTcpBinding b = new NetTcpBinding();
b.Security.Mode = SecurityMode.Message;
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows;

// Set a Type variable for use when constructing the endpoint.
Type c = typeof(ICalculator);

// Create a base address for the service.
Uri tcpBaseAddress =
    new Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName");
// The base address is in an array of URI objects.
Uri[] baseAddresses = new Uri[] { tcpBaseAddress };
// Create the ServiceHost with type and base addresses.
ServiceHost sh = new ServiceHost(typeof(CalculatorClient), baseAddresses);

// Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "");
sh.Open();
string address = sh.Description.Endpoints[0].ListenUri.AbsoluteUri;
Console.WriteLine($"Listening @ {address}");
Console.WriteLine("Press enter to close the service");
Console.ReadLine();
' Create a NetTcpBinding and set its security properties. The
' security mode is Message, and the client must be authenticated with
' Windows. Therefore the client must be on the same Windows ___domain.
Dim b As New NetTcpBinding()
b.Security.Mode = SecurityMode.Message
b.Security.Message.ClientCredentialType = MessageCredentialType.Windows

' Set a Type variable for use when constructing the endpoint.
Dim c As Type = GetType(ICalculator)

' Create a base address for the service.
Dim tcpBaseAddress As New Uri("net.tcp://machineName.Domain.Contoso.com:8036/serviceName")
' The base address is in an array of URI objects.
Dim baseAddresses() As Uri = {tcpBaseAddress}
' Create the ServiceHost with type and base addresses.
Dim sh As New ServiceHost(GetType(CalculatorClient), baseAddresses)

' Add an endpoint to the service using the service type and binding.
sh.AddServiceEndpoint(c, b, "")
sh.Open()
Dim address As String = sh.Description.Endpoints(0).ListenUri.AbsoluteUri
Console.WriteLine("Listening @ {0}", address)
Console.WriteLine("Press enter to close the service")
Console.ReadLine()

Consulte también