상호 인증서를 사용하는 메시지 보안
다음 시나리오는 메시지 보안 모드를 사용하여 보호되는 WCF(Windows Communication Foundation) 서비스 및 클라이언트를 보여 줍니다. 클라이언트 및 서비스는 인증서를 사용하여 인증됩니다.
이 시나리오는 X.509 인증서 토큰 프로필과 함께 WS-Security를 사용하므로 상호 운용할 수 있습니다.
참고 항목
이 시나리오에서는 서비스 인증서의 협상을 수행하지 않습니다. 서비스 인증서는 통신을 수행하기 전에 클라이언트에 제공해야 합니다. 서버 인증서는 애플리케이션과 함께 배포하거나 대역 외 통신에 제공할 수 있습니다.
특성 | 설명 |
---|---|
보안 모드 | 메시지 |
상호 운용성 | 예, 클라이언트 및 서비스와 호환되는 WS-Security 및 X.509 인증서 토큰 프로필과 상호 운용할 수 있습니다. |
인증 | 서버와 클라이언트의 상호 인증입니다. |
무결성 | 예 |
기밀성 | 예 |
전송 | HTTP |
바인딩 | WSHttpBinding |
서비스
다음 코드와 구성은 독립적으로 실행되어야 합니다. 다음 중 하나를 수행합니다.
구성 없이 코드를 사용하여 독립 실행형 서비스를 만듭니다.
제공된 구성을 사용하여 서비스를 만들지만 엔드포인트를 정의하지 않습니다.
코드
다음 코드에서는 메시지 보안을 사용하는 서비스 엔드포인트를 만드는 방법을 보여 줍니다. 서비스는 자신을 인증하기 위한 인증서가 필요합니다.
// Create the binding.
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType =
MessageCredentialType.Certificate;
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;
// Create the URI for the endpoint.
Uri httpUri = new Uri("http://localhost/Calculator");
// Create the service host.
ServiceHost myServiceHost =
new ServiceHost(typeof(Calculator), httpUri);
// Specify a certificate to authenticate the service.
myServiceHost.Credentials.ServiceCertificate.SetCertificate(
StoreLocation.LocalMachine,
StoreName.My,
X509FindType.FindBySubjectName,
"contoso.com");
// Add an endpoint to the service.
myServiceHost.AddServiceEndpoint(typeof(ICalculator), binding, "");
// Open the service.
myServiceHost.Open();
Console.WriteLine("Listening...");
Console.ReadLine();
// Close the service.
myServiceHost.Close();
' Create the binding.
Dim binding As New WSHttpBinding()
binding.Security.Mode = SecurityMode.Message
binding.Security.Message.ClientCredentialType = _
MessageCredentialType.Certificate
binding.Security.Message.NegotiateServiceCredential = False
binding.Security.Message.EstablishSecurityContext = False
' Create the URI for the endpoint.
Dim httpUri As New Uri("http://localhost/Calculator")
' Create the service host.
Dim myServiceHost As New ServiceHost(GetType(ServiceModel.Calculator), httpUri)
' Specify a certificate to authenticate the service.
myServiceHost.Credentials.ServiceCertificate.SetCertificate(StoreLocation.LocalMachine, _
StoreName.My, X509FindType.FindBySubjectName, "contoso.com")
' Add an endpoint to the service.
myServiceHost.AddServiceEndpoint(GetType(ICalculator), binding, "")
' Open the service.
myServiceHost.Open()
Console.WriteLine("Listening...")
Console.ReadLine()
' Close the service.
myServiceHost.Close()
구성
다음 구성은 동일한 서비스를 만드는 데 코드 대신 사용할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="serviceCredentialBehavior">
<serviceCredentials>
<serviceCertificate findValue="Contoso.com"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="serviceCredentialBehavior"
name="ServiceModel.Calculator">
<endpoint address="http://localhost/Calculator"
binding="wsHttpBinding"
bindingConfiguration="InteropCertificateBinding"
name="WSHttpBinding_ICalculator"
contract="ServiceModel.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="InteropCertificateBinding">
<security mode="Message">
<message clientCredentialType="Certificate"
negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client />
</system.serviceModel>
</configuration>
클라이언트
다음 코드와 구성은 독립적으로 실행되어야 합니다. 다음 중 하나를 수행합니다.
이 코드와 클라이언트 코드를 사용하여 독립 실행형 클라이언트를 만듭니다.
엔드포인트 주소를 정의하지 않는 클라이언트를 만듭니다. 대신 구성 이름을 인수로 사용하는 클라이언트 생성자를 사용합니다. 예시:
CalculatorClient cc = new CalculatorClient("EndpointConfigurationName");
Dim cc As New CalculatorClient("EndpointConfigurationName")
코드
다음 코드에서는 클라이언트를 만듭니다. 보안 모드는 Message로 설정되며 클라이언트 자격 증명 형식은 Certificate로 설정됩니다.
// Create the binding.
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
MessageCredentialType.Certificate;
// Disable credential negotiation and the establishment of
// a security context.
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;
// Create the endpoint address.
EndpointAddress ea = new
EndpointAddress("http://machineName/Calculator");
// Create the client.
CalculatorClient cc =
new CalculatorClient(myBinding, ea);
// Specify a certificate to use for authenticating the client.
cc.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser,
StoreName.My,
X509FindType.FindBySubjectName,
"Cohowinery.com");
// Specify a default certificate for the service.
cc.ClientCredentials.ServiceCertificate.SetDefaultCertificate(
StoreLocation.CurrentUser,
StoreName.TrustedPeople,
X509FindType.FindBySubjectName,
"Contoso.com");
// Begin using the client.
try
{
cc.Open();
Console.WriteLine(cc.Add(200, 1111));
Console.ReadLine();
// Close the client.
cc.Close();
}
' Create the binding.
Dim myBinding As New WSHttpBinding()
myBinding.Security.Mode = SecurityMode.Message
myBinding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate
' Disable credential negotiation and the establishment of
' a security context.
myBinding.Security.Message.NegotiateServiceCredential = False
myBinding.Security.Message.EstablishSecurityContext = False
' Create the endpoint address.
Dim ea As New EndpointAddress("http://localhost/Calculator")
' Create the client.
Dim cc As New CalculatorClient(myBinding, ea)
' Specify a certificate to use for authenticating the client.
cc.ClientCredentials.ClientCertificate.SetCertificate( _
StoreLocation.CurrentUser, StoreName.My, _
X509FindType.FindBySubjectName, "Cohowinery.com")
' Specify a default certificate for the service.
cc.ClientCredentials.ServiceCertificate.SetDefaultCertificate( _
StoreLocation.CurrentUser, StoreName.TrustedPeople, _
X509FindType.FindBySubjectName, "Contoso.com")
' Begin using the client.
Try
cc.Open()
Console.WriteLine(cc.Add(100, 11))
Console.ReadLine()
' Close the client.
cc.Close()
Catch tex As TimeoutException
Console.WriteLine(tex.Message)
cc.Abort()
Catch cex As CommunicationException
Console.WriteLine(cex.Message)
cc.Abort()
Finally
Console.WriteLine("Closed the client")
Console.ReadLine()
End Try
구성
다음과 같이 클라이언트를 구성합니다. <clientCertificate>를 사용하여 클라이언트 인증서를 지정해야 합니다. 또한 서비스 인증서는 <defaultCertificate>를 사용하여 지정됩니다.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCredentialsBehavior">
<clientCredentials>
<clientCertificate findValue="Cohowinery.com"
storeLocation="CurrentUser"
storeName="My"
x509FindType="FindBySubjectName" />
<serviceCertificate>
<defaultCertificate findValue="Contoso.com"
storeLocation="CurrentUser"
storeName="TrustedPeople"
x509FindType="FindBySubjectName" />
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_ICalculator" >
<security mode="Message">
<message clientCredentialType="Certificate"
negotiateServiceCredential="false"
establishSecurityContext="false" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://machineName/Calculator"
behaviorConfiguration="ClientCredentialsBehavior"
binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_ICalculator"
contract="ICalculator"
name="WSHttpBinding_ICalculator">
<identity>
<certificate encodedValue="Encoded_Value_Not_Shown" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>