다음을 통해 공유


Windows 인증 오류 디버그

Windows 인증을 보안 메커니즘으로 사용하면 SSPI(보안 지원 공급자 인터페이스)에서 보안 프로세스를 처리합니다. SSPI 계층에 보안 오류가 발생하면 WCF(Windows Communication Foundation)에 표시됩니다. 이 항목에서는 오류 진단에 도움이 되는 프레임워크 및 일련의 질문을 제공합니다.

Kerberos 프로토콜의 개요는 Kerberos Explained를 참조하고, SSPI의 개요는 SSPI를 참조하세요.

Windows 인증의 경우 일반적으로 WCF는 클라이언트와 서비스 간의 Kerberos 상호 인증을 수행하는 협상 SSP(보안 지원 공급자)를 사용합니다. Kerberos 프로토콜을 사용할 수 없는 경우 WCF에서는 기본적으로 NTLM(NT LAN Manager)으로 대체됩니다. 그러나 Kerberos 프로토콜만 사용하고 Kerberos를 사용할 수 없는 경우 예외를 throw하도록 WCF를 구성할 수 있습니다. 또한 제한된 형식의 Kerberos 프로토콜을 사용하도록 WCF를 구성할 수도 있습니다.

디버깅 방법

기본 방법은 다음과 같습니다.

  1. Windows 인증 사용 여부를 결정합니다. 다른 스키마를 사용할 경우 이 항목이 적용되지 않습니다.

  2. Windows 인증을 사용하는 경우 WCF 구성에서 Kerberos를 직접 사용할지 또는 협상을 통해 사용할지 결정합니다.

  3. 구성에서 Kerberos 프로토콜을 사용할지 또는 NTLM을 사용할지 결정한 다음에는 올바른 컨텍스트에서 오류 메시지를 이해할 수 있습니다.

Kerberos 프로토콜 및 NTLM 사용 가능성

Kerberos SSP에는 Kerberos KDC(키 배포 센터) 역할을 하는 도메인 컨트롤러가 있어야 합니다. Kerberos 프로토콜은 클라이언트와 서비스 둘 다에서 도메인 ID를 사용하는 경우에만 사용할 수 있습니다. 다음 표에 요약된 것처럼 다른 계정 조합의 경우 NTLM이 사용됩니다.

표 머리글에는 서버에서 사용할 수 있는 계정 형식이 표시되어 있으며, 왼쪽 열에는 클라이언트에서 사용할 수 있는 계정 형식이 표시되어 있습니다.

로컬 사용자 로컬 시스템 도메인 사용자 도메인 컴퓨터
로컬 사용자 NTLM NTLM NTLM NTLM
로컬 시스템 익명 NTLM 익명 NTLM 익명 NTLM 익명 NTLM
도메인 사용자 NTLM NTLM Kerberos Kerberos
도메인 컴퓨터 NTLM NTLM Kerberos Kerberos

특히 네 가지 계정 형식에는 다음이 포함됩니다.

  • 로컬 사용자: 시스템 전용 사용자 프로필. 예를 들어 MachineName\Administrator 또는 MachineName\ProfileName입니다.

  • 로컬 시스템: 도메인에 연결되지 않은 컴퓨터의 기본 제공 계정인 SYSTEM.

  • 도메인 사용자: Windows 도메인의 사용자 계정. 예: DomainName\ProfileName

  • 도메인 컴퓨터: Windows 도메인에 연결된 컴퓨터에서 실행 중인 컴퓨터 ID가 있는 프로세스. 예: MachineName\Network Service

참고 항목

서비스 자격 증명은 Open 클래스의 ServiceHost 메서드가 호출될 때 캡처됩니다. 클라이언트 자격 증명은 클라이언트가 메시지를 보낼 때마다 읽어 옵니다.

일반적인 Windows 인증 문제

이 단원에서는 몇 가지 일반적인 Windows 인증 문제와 그 해결 방법에 대해 설명합니다.

Kerberos 프로토콜

Kerberos 프로토콜에 대한 SPN/UPN 문제

Windows 인증을 사용할 때 Kerberos 프로토콜을 사용하거나 SSPI 협상을 수행하는 경우, 클라이언트 엔드포인트에 사용되는 URL은 서비스 URL 내에 있는 서비스 호스트의 정규화된 도메인 이름을 포함해야 합니다. 이 경우 서비스가 실행되고 있는 계정에는 시스템을 Active Directory 도메인에 추가할 때 만들어진 기본 시스템 SPN(서비스 사용자 이름) 키에 대한 액세스 권한이 있다고 가정합니다. 이 작업은 일반적으로 Network Service 계정으로 서비스를 실행하여 수행합니다. 서비스에 시스템 SPN 키에 대한 액세스 권한이 없는 경우 클라이언트의 엔드포인트 ID로 서비스가 실행 중인 계정의 올바른 SPN 또는 UPN(User Principal Name)을 제공해야 합니다. WCF가 SPN 및 UPN에서 작동하는 방식에 대한 자세한 내용은 서비스 ID 및 인증을 참조하세요.

웹 팜 또는 웹 가든과 같은 부하 분산 시나리오에서는 각 애플리케이션에 대해 고유한 계정을 정의하고, 해당 계정에 SPN을 할당하고, 애플리케이션의 모든 서비스가 해당 계정으로 실행되도록 하는 것이 일반적입니다.

서비스 계정에 대한 SPN을 얻으려면 Active Directory 도메인 관리자여야 합니다. 자세한 내용은 Windows용 Kerberos 기술 자료를 참조하세요.

Kerberos 프로토콜을 직접 사용하려면 도메인 컴퓨터 계정으로 서비스 실행이 필요

이는 다음 코드처럼 ClientCredentialType 속성이 Windows로 설정되고, NegotiateServiceCredential 속성이 false로 설정된 경우 발생합니다.

WSHttpBinding b = new WSHttpBinding();
// By default, the WSHttpBinding uses Windows authentication
// and Message mode.
b.Security.Message.NegotiateServiceCredential = false;
Dim b As New WSHttpBinding()
' By default, the WSHttpBinding uses Windows authentication 
' and Message mode.
b.Security.Message.NegotiateServiceCredential = False

이 문제를 해결하려면 도메인과 연결된 컴퓨터에서 Network Service 등의 도메인 컴퓨터 계정을 사용하여 서비스를 실행합니다.

위임에 자격 증명 협상 필요

Kerberos 인증 프로토콜을 위임과 함께 사용하려면 자격 증명 협상이 포함된 Kerberos 프로토콜("multi-leg" 또는 "multi-step" Kerberos라고 함)을 구현해야 합니다. 자격 증명 협상이 포함되지 않은 Kerberos 프로토콜("one-shot" 또는 "single-leg" Kerberos라고도 함)을 구현하면 예외가 throw됩니다.

자격 증명 협상이 포함된 Kerberos 프로토콜을 구현하려면 다음 단계를 수행합니다.

  1. AllowedImpersonationLevelDelegation으로 설정하여 위임을 구현합니다.

  2. SSPI 협상이 필요합니다.

    1. 표준 바인딩을 사용하는 경우 NegotiateServiceCredential 속성을 true로 설정합니다.

    2. 사용자 지정 바인딩을 사용하는 경우 AuthenticationMode 요소의 Security 속성을 SspiNegotiated로 설정합니다.

  3. NTLM 사용을 허용하지 않고 Kerberos를 사용하려면 SSPI 협상이 필요합니다.

    1. ChannelFactory.Credentials.Windows.AllowNtlm = false 문과 함께 코드에서 이 작업을 수행합니다.

    2. allowNtlm 특성을 false로 설정하여 구성 파일에서 이 작업을 수행할 수도 있습니다. 이 특성은 <windows>에 포함되어 있습니다.

NTLM 프로토콜

협상 SSP가 NTLM으로 대체되어도 NTLM을 사용하지 않도록 설정

AllowNtlm 속성이 false로 설정되어 있어 NTLM이 사용될 경우 WCF(Windows Communication Foundation)에서 예외가 throw됩니다. 이 속성을 false로 설정하면 유선을 통해 NTLM 자격 증명을 보낼 수 있습니다.

다음은 NTLM으로 대체되지 않도록 설정하는 방법을 보여 줍니다.

CalculatorClient cc = new
    CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.Windows.AllowNtlm = false;
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.Windows.AllowNtlm = False

NTLM 로그온 실패

클라이언트 자격 증명이 서비스에 유효하지 않습니다. 사용자 이름과 암호를 올바르게 설정했는지, 서비스를 실행하는 컴퓨터에서 인식하는 계정과 일치하는지 확인합니다. NTLM에서는 서비스의 컴퓨터에 로그온하기 위해 지정된 자격 증명을 사용합니다. 클라이언트를 실행하는 컴퓨터에서 유효한 자격 증명이라도 서비스의 컴퓨터에서 유효하지 않으면 로그온이 실패합니다.

익명 NTLM 로그온을 수행해도 기본적으로 익명 로그온을 사용하지 않도록 설정

클라이언트를 만들 때 다음 예제에서처럼 AllowedImpersonationLevel 속성이 Anonymous로 설정되지만 기본적으로 서버에서 익명 로그온을 허용하지 않습니다. 이는 AllowAnonymousLogons 클래스의 WindowsServiceCredential 속성의 기본값이 false로 설정되기 때문에 발생합니다.

다음 클라이언트 코드에서는 익명 로그온을 사용하도록 설정합니다. 기본 속성은 Identification입니다.

CalculatorClient cc =
    new CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Anonymous;
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Anonymous

다음 서비스 코드에서는 서버에서 익명 로그온을 사용하도록 기본값을 변경합니다.

Uri httpUri = new Uri("http://localhost:8000/");
ServiceHost sh = new ServiceHost(typeof(Calculator), httpUri);
sh.Credentials.WindowsAuthentication.AllowAnonymousLogons = true;
Dim httpUri As New Uri("http://localhost:8000/")
Dim sh As New ServiceHost(GetType(Calculator), httpUri)
sh.Credentials.WindowsAuthentication.AllowAnonymousLogons = True

가장에 대한 자세한 내용은 위임 및 가장을 참조하세요.

또는 기본 제공 계정인 SYSTEM을 사용하여 클라이언트를 Windows 서비스로 실행합니다.

기타 문제

클라이언트 자격 증명이 올바르게 설정되지 않음

Windows 인증에서는 WindowsClientCredential을 사용하지 않고, ClientCredentials 클래스의 ClientBase<TChannel> 속성에서 반환된 UserNamePasswordClientCredential 인스턴스를 사용합니다. 다음은 잘못된 예제입니다.

CalculatorClient cc = new
    CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.UserName.UserName = GetUserName(); // wrong!
cc.ClientCredentials.UserName.Password = GetPassword(); // wrong!
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.UserName.UserName = GetUserName() ' wrong!
cc.ClientCredentials.UserName.Password = GetPassword() ' wrong!

다음은 올바른 예제입니다.

CalculatorClient cc = new
    CalculatorClient("WSHttpBinding_ICalculator");
// This code returns the WindowsClientCredential type.
cc.ClientCredentials.Windows.ClientCredential.UserName = GetUserName();
cc.ClientCredentials.Windows.ClientCredential.Password = GetPassword();
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
' This code returns the WindowsClientCredential type.            
cc.ClientCredentials.Windows.ClientCredential.UserName = GetUserName()
cc.ClientCredentials.Windows.ClientCredential.Password = GetPassword()

SSPI를 사용할 수 없음

다음 운영 체제는 Windows XP Home Edition, Windows XP Media Center Edition, Windows Vista Home Edition과 같은 서버로 사용될 때 Windows 인증을 지원하지 않습니다.

다른 ID로 개발 및 배포

애플리케이션을 한 컴퓨터에서 개발하여 다른 컴퓨터에 배포하고 서로 다른 계정 형식을 사용하여 각 컴퓨터에서 인증을 수행하면 동작이 동일하지 않을 수 있습니다. 예를 들어 SSPI Negotiated 인증 모드를 사용하여 Windows XP Pro 컴퓨터에서 애플리케이션을 개발할 경우 로컬 사용자 계정을 사용하여 인증하면 NTLM 프로토콜이 사용됩니다. 애플리케이션 개발을 마친 후 도메인 계정으로 실행되는 Windows Server 2003 컴퓨터에 해당 서비스를 배포하면 클라이언트에서는 Kerberos 및 도메인 컨트롤러를 사용할 것이므로 해당 서비스를 인증할 수 없습니다.

참고 항목