次の方法で共有


Windows 認証エラーのデバッグ

セキュリティ機構として Windows 認証を使用する場合、セキュリティ サポート プロバイダー インターフェイス (SSPI: Security Support Provider Interface) がセキュリティ プロセスを処理します。 SSPI 層でセキュリティ エラーが発生すると、Windows Communication Foundation (WCF) によって示されます。 このトピックでは、エラーの診断に役立つフレームワークと一連の質問を示します。

Kerberos プロトコルの概要については、「Kerberos の説明」を参照してください。SSPI の概要については、「SSPI」を参照してください。

Windows 認証の場合、通常、WCF では Negotiate セキュリティ サポート プロバイダー (SSP: Security Support Provider) が使用されます。これは、クライアントとサービス間で Kerberos 相互認証を実行します。 Kerberos プロトコルを使用できない場合、既定では、WCF は NTLM (NT LAN Manager) にフォールバックされます。 ただし、Kerberos プロトコルのみを使用するように (Kerberos を使用できない場合は例外をスローするように) WCF を構成できます。 また、Kerberos プロトコルの制限付きの形式を使用するように WCF を構成することもできます。

デバッグ方法

基本的な方法は次のとおりです。

  1. Windows 認証を使用しているかどうかを確認します。 他の方式を使用している場合には、このトピックは該当しません。

  2. Windows 認証を使用していることが確実である場合は、WCF の構成で Kerberos ダイレクトと Negotiate のどちらを使用しているかを確認します。

  3. 構成で Kerberos プロトコルと NTLM のどちらを使用しているかを確認した後は、現在のコンテキストでのエラー メッセージを理解できます。

Kerberos プロトコルと NTLM の可用性

Kerberos SSP は、Kerberos キー配布センター (KDC: Key Distribution Center) として機能するドメイン コントローラーを必要とします。 Kerberos プロトコルを使用できるのは、クライアントとサービスの両方がドメイン ID を使用している場合だけです。 次の表に示すように、アカウントの他の組み合わせでは NTLM が使用されます。

この表の列見出しは、サーバーが使用すると考えられるアカウントの種類を示します。 左の列は、クライアントが使用すると考えられるアカウントの種類を示します。

Local User [ローカル システム] Domain User Domain Machine
Local User NTLM NTLM NTLM NTLM
Local System 匿名 NTLM 匿名 NTLM 匿名 NTLM 匿名 NTLM
Domain User NTLM NTLM Kerberos Kerberos
Domain Machine NTLM NTLM Kerberos Kerberos

具体的には、次の 4 種類のアカウントがあります。

  • Local User : コンピューター専用のユーザー プロファイル。 たとえば、MachineName\AdministratorMachineName\ProfileName などです。

  • Local System : ドメインに参加していないコンピューターの SYSTEM ビルトイン アカウント。

  • Domain User : Windows ドメインのユーザー アカウント。 たとえば、「DomainName\ProfileName」のように入力します。

  • Domain Machine : Windows ドメインに参加しているコンピューターで実行されている、コンピューター ID を使用するプロセス。 たとえば、「MachineName\Network Service」のように入力します。

注意

サービス資格情報は、Open クラスの ServiceHost メソッドが呼び出されたときにキャプチャされます。 クライアント資格情報は、クライアントがメッセージを送信するたびに読み取られます。

Windows 認証の一般的な問題

ここでは、Windows 認証に関するいくつかの一般的な問題と、考えられる解決策について説明します。

Kerberos プロトコル

Kerberos プロトコルでの SPN と UPN の問題

Windows 認証を使用し、SSPI が Kerberos プロトコルを使用またはネゴシエートする場合、クライアント エンドポイントが使用する URL には、サービス URL 内のサービスのホストの完全修飾ドメイン名が含まれている必要があります。 これは、サービスを実行しているアカウントがコンピューターの (既定の) サービス プリンシパル名 (SPN: Service Principal Name) キーにアクセスできることを前提としています。このキーは、コンピューターを Active Directory ドメインに追加したときに作成されます。コンピューターの SPN キーにアクセスできるようにするには、Network Service アカウントでサービスを実行するのが最も一般的な方法です。 サービスがコンピューターの SPN キーにアクセスできない場合は、クライアントのエンドポイント ID でサービスを実行しているアカウントの正しい SPN またはユーザー プリンシパル名 (UPN: User Principal Name) を指定する必要があります。 WCF における SPN と UPN の動作の詳細については、「サービス ID と認証」を参照してください。

Web ファームや Web ガーデンなどの負荷分散シナリオでは、各アプリケーションに一意のアカウントを定義し、そのアカウントに SPN を割り当て、アプリケーションのサービスすべてがそのアカウントで実行されるようにするのが一般的です。

サービスのアカウント用の SPN を取得するには、Active Directory ドメイン管理者である必要があります。 詳細については、「Kerberos に関する技術的な補足 (Windows 用)」を参照してください。

Kerberos プロトコル ダイレクトでは Domain Machine アカウントでサービスを実行する必要がある

この状況は、次のコードに示すように、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

これを解決するには、ドメインに参加しているコンピューターで、Domain Machine アカウント (Network Service など) を使用してサービスを実行します。

委任には資格情報ネゴシエーションが必要

委任で Kerberos 認証プロトコルを使用するには、資格情報ネゴシエーションを使用する Kerberos プロトコル ("マルチレッグ" Kerberos または "マルチステップ" Kerberos とも呼ばれます) を実装する必要があります。 資格情報ネゴシエーションを使用しない Kerberos 認証 ("ワンショット" Kerberos または "シングルレッグ" Kerberos とも呼ばれます) を実装した場合は、例外がスローされます。

資格情報ネゴシエーションを使用する Kerberos を実装するには、次の手順を実行します。

  1. AllowedImpersonationLevelDelegation に設定して委任を実装します。

  2. 次のような SSPI ネゴシエーションが必要です。

    1. 標準バインディングを使用する場合は、NegotiateServiceCredential プロパティを true に設定します。

    2. カスタム バインドを使用する場合は、AuthenticationMode 要素の Security 属性を SspiNegotiated に設定します。

  3. 次のように、NTLM を使用できないようにすることで、SSPI ネゴシエーションで Kerberos を使用する必要があります。

    1. NTLM を使用できないようにするには、コードで ChannelFactory.Credentials.Windows.AllowNtlm = false ステートメントを使用します。

    2. 構成ファイルで allowNtlm 属性を false に設定することもできます。 この属性は、<windows> に含まれています。

NTLM プロトコル

ネゴシエート SSP は NTLM にフォールバックするが、NTLM が無効になっている

AllowNtlm プロパティを false に設定すると、NTLM が使用されている場合に Windows Communication Foundation (WCF) によってベスト エフォートで例外がスローされるようになります。 このプロパティを 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

偽装の詳細については、委任と偽装に関するページを参照してください。

もう 1 つの方法として、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 を使用した開発と展開

アプリケーションを 1 台のコンピューターで開発し、別のコンピューターに展開し、異なるアカウントの種類を使用して各コンピューターで認証を行う場合、動作の違いが発生する場合があります。 たとえば、SSPI Negotiated 認証モードを使用して Windows XP Professional コンピューターでアプリケーションを開発するとします。 ローカル ユーザー アカウントを使用して認証する場合は、NTLM プロトコルが使用されます。 アプリケーションを開発した後は、ドメイン アカウントで実行されるサービスを Windows Server 2003 コンピューターに展開します。 この時点で、クライアントでは Kerberos とドメイン コントローラーが使用されるため、このサービスを認証できなくなります。

関連項目