다음을 통해 공유


WCF 보안 프로그래밍

이 항목에서는 보안 WCF(Windows Communication Foundation) 응용 프로그램을 만드는 데 사용되는 기본 프로그래밍 작업에 대해 설명합니다. 이 항목에서는 전송 보안으로 통칭되는 인증, 기밀성 및 무결성에 대해서만 설명합니다. 권한 부여(리소스 또는 서비스에 대한 액세스 제어)에 대해서는 이 항목에서 설명하지 않습니다. 권한 부여에 대한 자세한 내용은 권한 부여을(를) 참조하십시오.

ms731925.note(ko-kr,VS.100).gif참고:
보안 개념 특히, WCF와 관련된 중요한 정보는 MSDN의 Scenarios, Patterns, and Implementation Guidance for Web Services Enhancements (WSE) 3.0에 있는 패턴 및 실습 모음 자습서를 참조하십시오.

WCF 보안 프로그래밍은 보안 모드, 클라이언트 자격 증명 형식 및 자격 증명 값을 설정하는 세 가지 단계로 구성됩니다. 코드 또는 구성을 통해 이러한 단계를 수행할 수 있습니다.

보안 모드 설정

다음에서는 WCF에서 보안 모드로 프로그래밍하는 일반 단계에 대해 설명합니다.

  1. 응용 프로그램 요구 사항에 적합한 미리 정의된 바인딩 중 하나를 선택합니다. 바인딩 선택 목록은 시스템 제공 바인딩을(를) 참조하십시오. 기본적으로 거의 모든 바인딩에서 보안을 사용할 수 있습니다. 한 가지 예외는 BasicHttpBinding 클래스(구성 사용, basicHttpBinding Element)입니다.

    선택한 바인딩에 따라 전송이 결정됩니다. 예를 들어, WSHttpBinding에서는 HTTP를 전송으로 사용하고 NetTcpBinding에서는 TCP를 사용합니다.

  2. 바인딩에 대한 보안 모드 중 하나를 선택합니다. 선택한 바인딩에 따라 사용 가능한 모드 선택 사항이 결정됩니다. 예를 들어, WSDualHttpBinding에서는 전송 보안을 허용하지 않으므로, 전송 보안은 옵션이 아닙니다. 마찬가지로 MsmqIntegrationBindingNetNamedPipeBinding에서는 모두 메시지 보안을 허용하지 않습니다.

    다음과 같은 세 가지 선택 옵션이 있습니다.

    1. Transport

      전송 보안은 선택한 바인딩에서 사용하는 메커니즘에 종속됩니다. 예를 들어, WSHttpBinding을 사용하는 경우 보안 메커니즘은 SSL(Secure Sockets Layer)(또한 HTTPS에 대한 메커니즘)입니다. 일반적으로 전송 보안의 주요 이점은 사용 중인 전송에 관계 없이 처리 능력이 우수하다는 점입니다. 그러나 두 가지 제한이 있습니다. 첫째, 전송 메커니즘이 사용자를 인증하는 데 사용되는 자격 증명 형식을 지정합니다. 이는 서비스가 다른 형식의 자격 증명을 요구하는 다른 서비스와 상호 작용해야 하는 경우에만 단점이 됩니다. 둘째는 메시지 수준에서 보안이 적용되지 않기 때문에 종단 간 방식 대신 hop-by-hop 방식으로 보안이 구현됩니다. 이 제한은 클라이언트와 서비스 사이의 메시지 경로에 매개자가 포함되어 있는 경우에만 문제가 됩니다. 사용할 전송에 대한 자세한 내용은 , 전송 선택을 참조하십시오. 전송 보안 사용에 대한 자세한 내용은 전송 보안 개요를 참조하십시오.

    2. Message

      메시지 보안은 모든 메시지에 메시지를 보안된 상태로 유지하는 데 필요한 헤더와 데이터가 포함되어 있음을 의미합니다. 헤더의 구성이 다양하므로 여러 자격 증명을 포함할 수 있습니다. 이는 전송 메커니즘이 제공할 수 없는 특정 자격 증명 형식을 요구하는 다른 서비스와 상호 작용할 경우나 서비스마다 다른 자격 증명 형식을 요구하는 여러 서비스에서 메시지를 사용해야 하는 경우에 유용합니다.

      자세한 내용은 다음 항목을 참조하십시오. WCF의 메시지 보안.

    3. TransportWithMessageCredential

      이 선택 옵션에서는 전송 계층을 사용하여 메시지 전송을 보안하지만, 모든 메시지에 다른 서비스에 필요한 풍부한 자격 증명이 포함되어 있습니다. 이 옵션은 전송 보안의 성능 이점과 메시지 보안의 풍부한 자격 증명 이점을 결합합니다. BasicHttpBinding, WSFederationHttpBinding, NetPeerTcpBindingWSHttpBinding 바인딩에서 이 옵션을 사용할 수 있습니다.

  3. HTTP(HTTPS)에 대해 전송 보안을 사용하려면 SSL 인증서를 사용하여 호스트를 구성하고 포트에서 SSL을 사용하도록 설정해야 합니다. 자세한 내용은 다음 항목을 참조하십시오. HTTP 전송 보안.

  4. WSHttpBinding을 사용하고 보안 세션을 설정할 필요가 없는 경우 EstablishSecurityContext 속성을 false로 설정합니다.

    클라이언트와 서비스에서 대칭 키를 사용하여 채널을 만들 때(클라이언트와 서버가 대화 상자가 닫힐 때까지 대화 기간 동안 동일한 키를 사용), 보안 세션이 발생합니다.

클라이언트 자격 증명 형식 설정

클라이언트 자격 증명 형식을 적절하게 선택합니다. 자세한 내용은 다음 항목을 참조하십시오. 자격 증명 형식 선택. 다음과 같은 클라이언트 자격 증명 형식을 사용할 수 있습니다.

  • Windows

  • Certificate

  • Digest

  • Basic

  • UserName

  • NTLM

  • IssuedToken

모드 설정 방법에 따라 자격 증명 형식을 설정해야 합니다. 다음 구성 예제에 표시된 것처럼 wsHttpBinding을 선택하고 모드를 "Message"로 설정한 경우 메시지 요소의 clientCredentialType 특성 값을 None, Windows, UserName, Certificate, IssuedToken 중 하나로 설정할 수 있습니다.

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

코드

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

서비스 자격 증명 값 설정

클라이언트 자격 증명 형식을 선택한 경우 사용할 서비스 및 클라이언트에 대한 실제 자격 증명을 설정해야 합니다. 서비스에서 자격 증명은 ServiceCredentials 클래스를 사용하여 설정하고 ServiceHostBase 클래스의 Credentials 속성에 의해 반환됩니다. 사용 중인 바인딩은 서비스 자격 증명 형식, 선택한 보안 모드 및 클라이언트 자격 증명 형식을 함축합니다. 다음 코드에서는 서비스 자격 증명에 대한 인증서를 설정합니다.

' 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 commmunication error occurred: {0}", ce.Message)
    Console.WriteLine()
Catch exc As System.Exception
    Console.WriteLine("An unforseen error occurred: {0}", exc.Message)
    Console.ReadLine()
End Try
// 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 commmunication error occurred: {0}", ce.Message);
    Console.WriteLine();
}
catch (System.Exception exc)
{
    Console.WriteLine("An unforseen error occurred: {0}", exc.Message);
    Console.ReadLine();
}

클라이언트 자격 증명 값 설정

클라이언트에서 클라이언트 자격 증명 값은 ClientCredentials 클래스를 사용하여 설정하고 ClientBase 클래스의 ClientCredentials 속성에 의해 반환됩니다. 다음 코드에서는 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.
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()
// 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 @ {0}", address);
Console.WriteLine("Press enter to close the service");
Console.ReadLine();

참고 항목

기타 리소스

기본 WCF 프로그래밍
일반적인 보안 시나리오