Procedimiento para usar diferentes certificados X.509 para la firma y el cifrado

En este tema se muestra cómo configurar Windows Communication Foundation (WCF) a fin de usar certificados diferentes para la firma de mensajes y el cifrado tanto en el cliente como en el servicio.

A fin de poder utilizar certificados independientes para la firma y el cifrado, se debe crear un cliente personalizado o las credenciales de servicio (o ambos) porque WCF no proporciona una API para establecer varios clientes o certificados de servicio. Además, se debe proporcionar un administrador de tokens de seguridad para sacar el máximo partido a la información de varios certificados y crear un proveedor de tokens de seguridad adecuado para el uso de claves especificado y la dirección del mensaje.

El diagrama siguiente muestra las clases principales que se utilizan, las clases de las que se heredan (identificadas mediante una flecha que señala hacia arriba) y los tipos de valor devueltos de ciertos métodos y propiedades.

Chart showing how client credentials are used

Para obtener más información sobre las credenciales de cliente, vea Tutorial: Creación de credenciales de cliente y servicio personalizadas.

Además, debe crear un comprobador de identidad personalizado y vincularlo a un elemento de enlace de seguridad en un enlace personalizado. También debe utilizar las credenciales personalizadas en lugar de las credenciales predeterminadas.

En el diagrama siguiente, se muestran las clases implicadas en el enlace personalizado y cómo se vincula el comprobador de identidad personalizado. Hay varios elementos de enlace implicados. Todos ellos se heredan de BindingElement. AsymmetricSecurityBindingElement tiene la propiedad LocalClientSecuritySettings, que devuelve una instancia de IdentityVerifier, a partir de la cual se personaliza MyIdentityVerifier.

Chart showing a custom binding element

Para obtener más información sobre cómo crear un comprobador de identidad personalizado, vea Procedimientos para crear un comprobador de identidad de clientes personalizado.

Para utilizar certificados independientes para la firma y el cifrado

  1. Defina una nueva clase de credenciales de cliente que herede de la clase ClientCredentials. Implemente cuatro nuevas propiedades para permitir la especificación de múltiples certificados: ClientSigningCertificate, ClientEncryptingCertificate, ServiceSigningCertificate y ServiceEncryptingCertificate. Invalide también el método CreateSecurityTokenManager para devolver una instancia de la clase ClientCredentialsSecurityTokenManager personalizada que se define en el paso siguiente.

    public class MyClientCredentials : ClientCredentials
    {
        X509Certificate2 clientSigningCert;
        X509Certificate2 clientEncryptingCert;
        X509Certificate2 serviceSigningCert;
        X509Certificate2 serviceEncryptingCert;
    
        public MyClientCredentials()
        {
        }
    
        protected MyClientCredentials(MyClientCredentials other)
            : base(other)
        {
            this.clientEncryptingCert = other.clientEncryptingCert;
            this.clientSigningCert = other.clientSigningCert;
            this.serviceEncryptingCert = other.serviceEncryptingCert;
            this.serviceSigningCert = other.serviceSigningCert;
        }
    
        public X509Certificate2 ClientSigningCertificate
        {
            get
            {
                return this.clientSigningCert;
            }
            set
            {
                this.clientSigningCert = value;
            }
        }
    
        public X509Certificate2 ClientEncryptingCertificate
        {
            get
            {
                return this.clientEncryptingCert;
            }
            set
            {
                this.clientEncryptingCert = value;
            }
        }
    
        public X509Certificate2 ServiceSigningCertificate
        {
            get
            {
                return this.serviceSigningCert;
            }
            set
            {
                this.serviceSigningCert = value;
            }
        }
    
        public X509Certificate2 ServiceEncryptingCertificate
        {
            get
            {
                return this.serviceEncryptingCert;
            }
            set
            {
                this.serviceEncryptingCert = value;
            }
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new MyClientCredentialsSecurityTokenManager(this);
        }
    
        protected override ClientCredentials CloneCore()
        {
            return new MyClientCredentials(this);
        }
    }
    
    Public Class MyClientCredentials
        Inherits ClientCredentials
    
        Private clientSigningCert As X509Certificate2
        Private clientEncryptingCert As X509Certificate2
        Private serviceSigningCert As X509Certificate2
        Private serviceEncryptingCert As X509Certificate2
    
        Public Sub New()
        End Sub
    
        Protected Sub New(ByVal other As MyClientCredentials)
            MyBase.New(other)
            Me.clientEncryptingCert = other.clientEncryptingCert
            Me.clientSigningCert = other.clientSigningCert
            Me.serviceEncryptingCert = other.serviceEncryptingCert
            Me.serviceSigningCert = other.serviceSigningCert
        End Sub
    
        Public Property ClientSigningCertificate() As X509Certificate2
            Get
                Return Me.clientSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientSigningCert = value
            End Set
        End Property
    
        Public Property ClientEncryptingCertificate() As X509Certificate2
            Get
                Return Me.clientEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientEncryptingCert = value
            End Set
        End Property
    
        Public Property ServiceSigningCertificate() As X509Certificate2
            Get
                Return Me.serviceSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceSigningCert = value
            End Set
        End Property
    
        Public Property ServiceEncryptingCertificate() As X509Certificate2
            Get
                Return Me.serviceEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceEncryptingCert = value
            End Set
        End Property
    
        Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
            Return New MyClientCredentialsSecurityTokenManager(Me)
        End Function
    
        Protected Overrides Function CloneCore() As ClientCredentials
            Return New MyClientCredentials(Me)
        End Function
    
    End Class
    
  2. Defina un nuevo administrador de tokens de seguridad del cliente que herede de la clase ClientCredentialsSecurityTokenManager. Invalide el método CreateSecurityTokenProvider para crear un proveedor de tokens de seguridad adecuado. El parámetro requirement (un SecurityTokenRequirement) proporciona la dirección del mensaje y el uso de las claves.

    internal class MyClientCredentialsSecurityTokenManager :
        ClientCredentialsSecurityTokenManager
    {
        MyClientCredentials credentials;
    
        public MyClientCredentialsSecurityTokenManager(
            MyClientCredentials credentials): base(credentials)
        {
            this.credentials = credentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(
            SecurityTokenRequirement requirement)
        {
            SecurityTokenProvider result = null;
            if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
            {
                MessageDirection direction = requirement.GetProperty
                    <MessageDirection>(ServiceModelSecurityTokenRequirement.
                    MessageDirectionProperty);
                if (direction == MessageDirection.Output)
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Signature)
                    {
                        result = new X509SecurityTokenProvider(
                            this.credentials.ClientSigningCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(this.credentials.
                            ServiceEncryptingCertificate);
                    }
                }
                else
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Signature)
                    {
                        result = new X509SecurityTokenProvider(this.
                            credentials.ServiceSigningCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(credentials.
                            ClientEncryptingCertificate);
                    }
                }
            }
            else
            {
                result = base.CreateSecurityTokenProvider(requirement);
            }
    
            return result;
        }
    
        public override SecurityTokenAuthenticator
            CreateSecurityTokenAuthenticator(SecurityTokenRequirement
            tokenRequirement, out SecurityTokenResolver outOfBandTokenResolver)
        {
            return base.CreateSecurityTokenAuthenticator(tokenRequirement,
                out outOfBandTokenResolver);
        }
    }
    
    Friend Class MyClientCredentialsSecurityTokenManager
        Inherits ClientCredentialsSecurityTokenManager
    
        Private credentials As MyClientCredentials
    
        Public Sub New(ByVal credentials As MyClientCredentials)
            MyBase.New(credentials)
            Me.credentials = credentials
        End Sub
    
        Public Overrides Function CreateSecurityTokenProvider(ByVal requirement As SecurityTokenRequirement) As SecurityTokenProvider
            Dim result As SecurityTokenProvider = Nothing
            If requirement.TokenType = SecurityTokenTypes.X509Certificate Then
                Dim direction = requirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
                If direction = MessageDirection.Output Then
                    If requirement.KeyUsage = SecurityKeyUsage.Signature Then
                        result = New X509SecurityTokenProvider(Me.credentials.ClientSigningCertificate)
                    Else
                        result = New X509SecurityTokenProvider(Me.credentials.ServiceEncryptingCertificate)
                    End If
                Else
                    If requirement.KeyUsage = SecurityKeyUsage.Signature Then
                        result = New X509SecurityTokenProvider(Me.credentials.ServiceSigningCertificate)
                    Else
                        result = New X509SecurityTokenProvider(credentials.ClientEncryptingCertificate)
                    End If
                End If
            Else
                result = MyBase.CreateSecurityTokenProvider(requirement)
            End If
    
            Return result
        End Function
    
        Public Overrides Function CreateSecurityTokenAuthenticator(ByVal tokenRequirement As SecurityTokenRequirement, _
                                                                   <System.Runtime.InteropServices.Out()> ByRef outOfBandTokenResolver As SecurityTokenResolver) As SecurityTokenAuthenticator
            Return MyBase.CreateSecurityTokenAuthenticator(tokenRequirement, _
                                                           outOfBandTokenResolver)
        End Function
    
    End Class
    
  3. Defina una nueva clase de credenciales de servicio que hereda de la clase ServiceCredentials. Implemente cuatro nuevas propiedades para permitir la especificación de múltiples certificados: ClientSigningCertificate, ClientEncryptingCertificate, ServiceSigningCertificate y ServiceEncryptingCertificate. Invalide también el método CreateSecurityTokenManager para devolver una instancia de la clase ServiceCredentialsSecurityTokenManager personalizada que se define en el paso siguiente.

    public class MyServiceCredentials : ServiceCredentials
    {
        X509Certificate2 clientSigningCert;
        X509Certificate2 clientEncryptingCert;
        X509Certificate2 serviceSigningCert;
        X509Certificate2 serviceEncryptingCert;
    
        public MyServiceCredentials()
        {
        }
    
        protected MyServiceCredentials(MyServiceCredentials other)
            : base(other)
        {
            this.clientEncryptingCert = other.clientEncryptingCert;
            this.clientSigningCert = other.clientSigningCert;
            this.serviceEncryptingCert = other.serviceEncryptingCert;
            this.serviceSigningCert = other.serviceSigningCert;
        }
    
        public X509Certificate2 ClientSigningCertificate
        {
            get
            {
                return this.clientSigningCert;
            }
            set
            {
                this.clientSigningCert = value;
            }
        }
    
        public X509Certificate2 ClientEncryptingCertificate
        {
            get
            {
                return this.clientEncryptingCert;
            }
            set
            {
                this.clientEncryptingCert = value;
            }
        }
    
        public X509Certificate2 ServiceSigningCertificate
        {
            get
            {
                return this.serviceSigningCert;
            }
            set
            {
                this.serviceSigningCert = value;
            }
        }
    
        public X509Certificate2 ServiceEncryptingCertificate
        {
            get
            {
                return this.serviceEncryptingCert;
            }
            set
            {
                this.serviceEncryptingCert = value;
            }
        }
    
        public override SecurityTokenManager CreateSecurityTokenManager()
        {
            return new MyServiceCredentialsSecurityTokenManager(this);
        }
    
        protected override ServiceCredentials CloneCore()
        {
            return new MyServiceCredentials(this);
        }
    }
    
    Public Class MyServiceCredentials
        Inherits ServiceCredentials
    
        Private clientSigningCert As X509Certificate2
        Private clientEncryptingCert As X509Certificate2
        Private serviceSigningCert As X509Certificate2
        Private serviceEncryptingCert As X509Certificate2
    
        Public Sub New()
        End Sub
    
        Protected Sub New(ByVal other As MyServiceCredentials)
            MyBase.New(other)
            Me.clientEncryptingCert = other.clientEncryptingCert
            Me.clientSigningCert = other.clientSigningCert
            Me.serviceEncryptingCert = other.serviceEncryptingCert
            Me.serviceSigningCert = other.serviceSigningCert
        End Sub
    
        Public Property ClientSigningCertificate() As X509Certificate2
            Get
                Return Me.clientSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientSigningCert = value
            End Set
        End Property
    
        Public Property ClientEncryptingCertificate() As X509Certificate2
            Get
                Return Me.clientEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.clientEncryptingCert = value
            End Set
        End Property
    
        Public Property ServiceSigningCertificate() As X509Certificate2
            Get
                Return Me.serviceSigningCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceSigningCert = value
            End Set
        End Property
    
        Public Property ServiceEncryptingCertificate() As X509Certificate2
            Get
                Return Me.serviceEncryptingCert
            End Get
            Set(ByVal value As X509Certificate2)
                Me.serviceEncryptingCert = value
            End Set
        End Property
    
        Public Overrides Function CreateSecurityTokenManager() As SecurityTokenManager
            Return New MyServiceCredentialsSecurityTokenManager(Me)
        End Function
    
        Protected Overrides Function CloneCore() As ServiceCredentials
            Return New MyServiceCredentials(Me)
        End Function
    
    End Class
    
  4. Defina un nuevo administrador de tokens de seguridad de servicio que herede de la clase ServiceCredentialsSecurityTokenManager. Invalide el método CreateSecurityTokenProvider para crear un proveedor de tokens de seguridad adecuado dada la dirección del mensaje pasada y el uso de las claves.

    internal class MyServiceCredentialsSecurityTokenManager :
        ServiceCredentialsSecurityTokenManager
    {
        MyServiceCredentials credentials;
    
        public MyServiceCredentialsSecurityTokenManager(
            MyServiceCredentials credentials)
            : base(credentials)
        {
            this.credentials = credentials;
        }
    
        public override SecurityTokenProvider CreateSecurityTokenProvider(
            SecurityTokenRequirement requirement)
        {
            SecurityTokenProvider result = null;
            if (requirement.TokenType == SecurityTokenTypes.X509Certificate)
            {
                MessageDirection direction = requirement.
                    GetProperty<MessageDirection>(
                    ServiceModelSecurityTokenRequirement.
                    MessageDirectionProperty);
                if (direction == MessageDirection.Input)
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Exchange)
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ServiceEncryptingCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ClientSigningCertificate);
                    }
                }
                else
                {
                    if (requirement.KeyUsage == SecurityKeyUsage.Signature)
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ServiceSigningCertificate);
                    }
                    else
                    {
                        result = new X509SecurityTokenProvider(
                            credentials.ClientEncryptingCertificate);
                    }
                }
            }
            else
            {
                result = base.CreateSecurityTokenProvider(requirement);
            }
            return result;
        }
    }
    
    Friend Class MyServiceCredentialsSecurityTokenManager
        Inherits ServiceCredentialsSecurityTokenManager
    
        Private credentials As MyServiceCredentials
    
        Public Sub New(ByVal credentials As MyServiceCredentials)
            MyBase.New(credentials)
            Me.credentials = credentials
        End Sub
    
        Public Overrides Function CreateSecurityTokenProvider(ByVal requirement As SecurityTokenRequirement) As SecurityTokenProvider
            Dim result As SecurityTokenProvider = Nothing
            If requirement.TokenType = SecurityTokenTypes.X509Certificate Then
                Dim direction = requirement.GetProperty(Of MessageDirection)(ServiceModelSecurityTokenRequirement.MessageDirectionProperty)
                If direction = MessageDirection.Input Then
                    If requirement.KeyUsage = SecurityKeyUsage.Exchange Then
                        result = New X509SecurityTokenProvider(credentials.ServiceEncryptingCertificate)
                    Else
                        result = New X509SecurityTokenProvider(credentials.ClientSigningCertificate)
                    End If
                Else
                    If requirement.KeyUsage = SecurityKeyUsage.Signature Then
                        result = New X509SecurityTokenProvider(credentials.ServiceSigningCertificate)
                    Else
                        result = New X509SecurityTokenProvider(credentials.ClientEncryptingCertificate)
                    End If
                End If
            Else
                result = MyBase.CreateSecurityTokenProvider(requirement)
            End If
            Return result
        End Function
    
    End Class
    

Para utilizar varios certificados en el cliente

  1. Cree un enlace personalizado. El elemento de enlace de seguridad debe funcionar en modo dúplex para permitir que distintos proveedores de tokens de seguridad estén presentes para las solicitudes y respuestas. Una manera de hacerlo es utilizar un transporte de tipo dúplex o utilizar CompositeDuplexBindingElement tal y como se muestra en el código siguiente. Vincule el objeto IdentityVerifier personalizado que se define en el paso siguiente al elemento de enlace de seguridad. Reemplace las credenciales de cliente predeterminadas con las credenciales de cliente personalizadas creadas previamente.

                EndpointAddress serviceEndpoint =
                    new EndpointAddress(new Uri("http://localhost:6060/service"));
    
                CustomBinding binding = new CustomBinding();
    
                AsymmetricSecurityBindingElement securityBE =
                    SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(
                    MessageSecurityVersion.
    WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10);
                // Add a custom IdentityVerifier because the service uses two certificates
                // (one for signing and one for encryption) and an endpoint identity that
                // contains a single identity claim.
                securityBE.LocalClientSettings.IdentityVerifier = new MyIdentityVerifier();
                binding.Elements.Add(securityBE);
    
                CompositeDuplexBindingElement compositeDuplex =
                    new CompositeDuplexBindingElement();
                compositeDuplex.ClientBaseAddress = new Uri("http://localhost:6061/client");
                binding.Elements.Add(compositeDuplex);
    
                binding.Elements.Add(new OneWayBindingElement());
    
                binding.Elements.Add(new HttpTransportBindingElement());
    
                using (ChannelFactory<IMyServiceChannel> factory =
                    new ChannelFactory<IMyServiceChannel>(binding, serviceEndpoint))
                {
                    MyClientCredentials credentials = new MyClientCredentials();
                    SetupCertificates(credentials);
                    factory.Endpoint.Behaviors.Remove(typeof(ClientCredentials));
                    factory.Endpoint.Behaviors.Add(credentials);
    
                    IMyServiceChannel channel = factory.CreateChannel();
                    Console.WriteLine(channel.Hello("world"));
                    channel.Close();
                }
    
    Dim serviceEndpoint As New EndpointAddress(New Uri("http://localhost:6060/service"))
    
    Dim binding As New CustomBinding()
    
    Dim securityBE = SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10)
    ' Add a custom IdentityVerifier because the service uses two certificates 
    ' (one for signing and one for encryption) and an endpoint identity that 
    ' contains a single identity claim.
    securityBE.LocalClientSettings.IdentityVerifier = New MyIdentityVerifier()
    binding.Elements.Add(securityBE)
    
    Dim compositeDuplex As New CompositeDuplexBindingElement()
    
    compositeDuplex.ClientBaseAddress = New Uri("http://localhost:6061/client")
    
    With binding.Elements
        .Add(compositeDuplex)
        .Add(New OneWayBindingElement())
        .Add(New HttpTransportBindingElement())
    End With
    
    Using factory As New ChannelFactory(Of IMyServiceChannel)(binding, serviceEndpoint)
        Dim credentials As New MyClientCredentials()
        SetupCertificates(credentials)
    
        With factory.Endpoint.Behaviors
            .Remove(GetType(ClientCredentials))
            .Add(credentials)
        End With
    
        Dim channel = factory.CreateChannel()
        Console.WriteLine(channel.Hello("world"))
        channel.Close()
    End Using
    
  2. Defina un objeto IdentityVerifier personalizado. El servicio tiene varias identidades porque se usan certificados diferentes para cifrar la solicitud y firmar la respuesta.

    Nota:

    En el ejemplo siguiente, el comprobador de identidad personalizado proporcionado no realiza ninguna comprobación de identidad del punto de conexión con fines de demostración. No se trata de una práctica recomendada para el código de producción.

    class MyIdentityVerifier : IdentityVerifier
    {
        IdentityVerifier defaultVerifier;
    
        public MyIdentityVerifier()
        {
            this.defaultVerifier = IdentityVerifier.CreateDefault();
        }
    
        public override bool CheckAccess(EndpointIdentity identity,
            AuthorizationContext authContext)
        {
            // The following implementation is for demonstration only, and
            // does not perform any checks regarding EndpointIdentity.
            // Do not use this for production code.
            return true;
        }
    
        public override bool TryGetIdentity(EndpointAddress reference,
            out EndpointIdentity identity)
        {
            return this.defaultVerifier.TryGetIdentity(reference, out identity);
        }
    }
    
    
    Friend Class MyIdentityVerifier
        Inherits IdentityVerifier
    
        Private defaultVerifier As IdentityVerifier
    
        Public Sub New()
            Me.defaultVerifier = IdentityVerifier.CreateDefault()
        End Sub
    
        Public Overrides Function CheckAccess(ByVal identity As EndpointIdentity, ByVal authContext As AuthorizationContext) As Boolean
            ' The following implementation is for demonstration only, and
            ' does not perform any checks regarding EndpointIdentity.
            ' Do not use this for production code.
            Return True
        End Function
    
        Public Overrides Function TryGetIdentity(ByVal reference As EndpointAddress, <System.Runtime.InteropServices.Out()> ByRef identity As EndpointIdentity) As Boolean
            Return Me.defaultVerifier.TryGetIdentity(reference, identity)
        End Function
    
    End Class
    

Para utilizar varios certificados en el servicio

  1. Cree un enlace personalizado. El elemento de enlace de seguridad debe funcionar en modo dúplex para permitir que distintos proveedores de tokens de seguridad estén presentes para las solicitudes y respuestas. Tal y como ocurre con el cliente, utilice un transporte de tipo dúplex o use CompositeDuplexBindingElement tal y como se muestra en el código siguiente. Reemplace las credenciales de servicio predeterminadas con las credenciales de servicio personalizadas creadas previamente.

                Uri serviceEndpoint = new Uri("http://localhost:6060/service");
                using (ServiceHost host = new ServiceHost(typeof(Service), serviceEndpoint))
                {
                    CustomBinding binding = new CustomBinding();
                    binding.Elements.Add(SecurityBindingElement.
                        CreateMutualCertificateDuplexBindingElement(
    MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10));
                    binding.Elements.Add(new CompositeDuplexBindingElement());
                    binding.Elements.Add(new OneWayBindingElement());
                    binding.Elements.Add(new HttpTransportBindingElement());
    
                    MyServiceCredentials credentials = new MyServiceCredentials();
                    SetupCertificates(credentials);
                    host.Description.Behaviors.Remove(typeof(ServiceCredentials));
                    host.Description.Behaviors.Add(credentials);
    
                    ServiceEndpoint endpoint = host.AddServiceEndpoint(
                        typeof(IMyService), binding, "");
                    host.Open();
    
                    Console.WriteLine("Service started, press ENTER to stop...");
                    Console.ReadLine();
                }
    
    Dim serviceEndpoint As New Uri("http://localhost:6060/service")
    Using host As New ServiceHost(GetType(Service), serviceEndpoint)
        Dim binding As New CustomBinding()
    
        With binding.Elements
            .Add(SecurityBindingElement.CreateMutualCertificateDuplexBindingElement(MessageSecurityVersion.WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10))
            .Add(New CompositeDuplexBindingElement())
            .Add(New OneWayBindingElement())
            .Add(New HttpTransportBindingElement())
        End With
    
        Dim credentials As New MyServiceCredentials()
        SetupCertificates(credentials)
        With host.Description.Behaviors
            .Remove(GetType(ServiceCredentials))
            .Add(credentials)
        End With
    
        Dim endpoint = host.AddServiceEndpoint(GetType(IMyService), binding, "")
        host.Open()
    
        Console.WriteLine("Service started, press ENTER to stop...")
        Console.ReadLine()
    End Using
    

Consulte también