다음을 통해 공유


방법: 서명 및 암호화에 별도의 X.509 인증서 사용

이 항목에서는 클라이언트와 서비스 모두에서 메시지 서명 및 암호화에 서로 다른 인증서를 사용하도록 WCF(Windows Communication Foundation)를 구성하는 방법을 보여 줍니다.

WCF에서 여러 클라이언트 또는 서비스 인증서를 설정하는 API를 제공하지 않기 때문에 서명 및 암호화에 별도의 인증서를 사용하려면 사용자 지정 클라이언트 또는 서비스 자격 증명(또는 둘 다)을 만들어야 합니다. 또한 여러 개의 인증서 정보를 활용하고 지정된 키 사용과 메시지 방향에 적합한 보안 토큰 공급자를 만들기 위해 보안 토큰 관리자도 제공되어야 합니다.

다음 다이어그램에서는 사용되는 주 클래스, 상속하는 클래스(위쪽 화살표로 표시), 특정 메서드 및 속성의 반환 형식을 보여 줍니다.

Chart showing how client credentials are used

사용자 지정 자격 증명에 대한 자세한 내용은 연습: 사용자 지정 클라이언트 및 서비스 자격 증명 만들기를 참조하세요.

또한 사용자 지정 ID 검증 도구를 만들고 사용자 지정 바인딩의 보안 바인딩 요소에 연결해야 합니다. 그리고 기본 자격 증명 대신 사용자 지정 자격 증명을 사용해야 합니다.

다음 다이어그램에서는 사용자 지정 바인딩에 관련된 클래스 및 사용자 지정 ID 검증 도구를 연결하는 방법을 보여 줍니다. 여러 바인딩 요소가 관련되어 있으며 이들 요소는 모두 BindingElement에서 상속합니다. AsymmetricSecurityBindingElement에는 LocalClientSecuritySettings 속성이 있습니다. 이 속성은 IdentityVerifier가 사용자 지정되는 MyIdentityVerifier인스턴스를 반환합니다.

Chart showing a custom binding element

사용자 지정 ID 확인 도구를 만드는 방법에 대한 자세한 내용은 방법: 방법: 사용자 지정 클라이언트 ID 확인 도구 만들기를 참조하세요.

서명 및 암호화에 별도의 인증서를 사용하려면

  1. ClientCredentials 클래스에서 상속되는 새로운 클라이언트 자격 증명 클래스를 정의합니다. 여러 인증서 지정을 허용하는 네 가지 새 속성인 ClientSigningCertificate, ClientEncryptingCertificate, ServiceSigningCertificateServiceEncryptingCertificate및 를 구현합니다. 또한 CreateSecurityTokenManager 메서드를 재정의하여 다음 단계에 정의된 사용자 지정된 ClientCredentialsSecurityTokenManager 클래스의 인스턴스를 반환합니다.

    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. ClientCredentialsSecurityTokenManager 클래스에서 상속되는 새로운 클라이언트 보안 토큰 관리자를 정의합니다. 올바른 보안 토큰 공급자를 만들기 위해 CreateSecurityTokenProvider 메서드를 재정의합니다. 메시지 방향과 키 사용은 requirement 매개 변수(SecurityTokenRequirement)를 통해 제공됩니다.

    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. ServiceCredentials 클래스에서 상속되는 새로운 서비스 자격 증명 클래스를 정의합니다. 여러 인증서 지정을 허용하는 네 가지 새 속성인 ClientSigningCertificate, ClientEncryptingCertificate, ServiceSigningCertificateServiceEncryptingCertificate및 를 구현합니다. 또한 CreateSecurityTokenManager 메서드를 재정의하여 다음 단계에 정의된 사용자 지정된 ServiceCredentialsSecurityTokenManager 클래스의 인스턴스를 반환합니다.

    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. ServiceCredentialsSecurityTokenManager 클래스에서 상속되는 새로운 서비스 보안 토큰 관리자를 정의합니다. 전달된 메시지 방향과 키 사용에 적합한 보안 토큰 공급자를 만들기 위해 CreateSecurityTokenProvider 메서드를 재정의합니다.

    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
    

클라이언트에 여러 인증서를 사용하려면

  1. 사용자 지정 바인딩을 만듭니다. 보안 바인딩 요소는 요청 및 응답에 서로 다른 보안 토큰 공급자를 사용할 수 있도록 이중 모드로 작동되어야 합니다. 이를 위한 한 가지 방법은 다음 코드에서와 같이 CompositeDuplexBindingElement를 사용하거나 이중 가능 전송을 사용하는 것입니다. 다음 단계에 정의된 사용자 지정된 IdentityVerifier를 보안 바인딩 요소에 연결합니다. 기본 클라이언트 자격 증명을 이전에 만든 사용자 지정된 클라이언트 자격 증명으로 바꿉니다.

                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. 사용자 지정 IdentityVerifier를 정의합니다. 요청을 암호화하고 응답을 서명하는 데 서로 다른 인증서가 사용되므로 서비스에는 여러 개의 ID가 있습니다.

    참고 항목

    다음 샘플에 제공된 사용자 지정 ID 검증 도구는 엔드포인트 ID 확인을 수행하지 않는 데모용이므로, 프로덕션 코드에 사용하지 않는 것이 좋습니다.

    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
    

서비스에 여러 인증서를 사용하려면

  1. 사용자 지정 바인딩을 만듭니다. 보안 바인딩 요소는 요청 및 응답에 서로 다른 보안 토큰 공급자를 사용할 수 있도록 이중 모드로 작동되어야 합니다. 클라이언트와 마찬가지로, 다음 코드에서와 같이 CompositeDuplexBindingElement를 사용하거나 이중 가능 전송을 사용합니다. 기본 서비스 자격 증명을 이전에 만든 사용자 지정된 서비스 자격 증명으로 바꿉니다.

                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
    

참고 항목