Windows 認証エラーのデバッグ
セキュリティ機構として Windows 認証を使用する場合、セキュリティ サポート プロバイダー インターフェイス (SSPI: Security Support Provider Interface) がセキュリティ プロセスを処理します。SSPI 層でセキュリティ エラーが発生すると、Windows Communication Foundation (WCF) によってこれらのエラーが示されます。このトピックでは、エラーの診断に役立つフレームワークと一連の質問を示します。
Kerberos プロトコルの概要については、「Kerberos の説明」を参照してください。SSPI の概要については、「SSPI」を参照してください。
Windows 認証の場合、通常、WCF はネゴシエート セキュリティ サポート プロバイダー (SSP: Security Support Provider) を使用します。ネゴシエート SSP は、クライアントとサービス間で Kerberos 相互認証を実行します。Kerberos プロトコルを使用できない場合、既定では、WCF は NTLM (NT LAN Manager) にフォールバックします。ただし、Kerberos プロトコルのみを使用するように (Kerberos を使用できない場合は例外をスローするように) WCF を構成できます。また、Kerberos プロトコルの制限付きの形式を使用するように WCF を構成することもできます。
デバッグ方法
基本的な方法は次のとおりです。
Windows 認証を使用しているかどうかを確認します。他の方式を使用している場合には、このトピックは該当しません。
Windows 認証を使用していることが確実である場合は、WCF の構成で Kerberos ダイレクトと Negotiate のどちらを使用しているかを確認します。
構成で Kerberos プロトコルと NTLM のどちらを使用しているかを確認した後は、現在のコンテキストでのエラー メッセージを理解できます。
Kerberos プロトコルと NTLM の可用性
Kerberos SSP は、Kerberos キー配布センター (KDC: Key Distribution Center) として機能するドメイン コントローラーを必要とします。Kerberos プロトコルを使用できるのは、クライアントとサービスの両方がドメイン ID を使用している場合だけです。次の表に示すように、アカウントの他の組み合わせでは NTLM が使用されます。
この表の列見出しは、サーバーが使用すると考えられるアカウントの種類を示します。左の列は、クライアントが使用すると考えられるアカウントの種類を示します。
Local User | Local System | Domain User | Domain Machine | |
---|---|---|---|---|
Local User |
NTLM |
NTLM |
NTLM |
NTLM |
ローカル システム |
匿名 NTLM |
匿名 NTLM |
匿名 NTLM |
匿名 NTLM |
Domain User |
NTLM |
NTLM |
Kerberos |
Kerberos |
Domain Machine |
NTLM |
NTLM |
Kerberos |
Kerberos |
具体的には、次の 4 種類のアカウントがあります。
Local User : コンピューター専用のユーザー プロファイル。例 : MachineName\Administrator または MachineName\ProfileName。
Local System : ドメインに参加していないコンピューターの SYSTEM ビルトイン アカウント。
Domain User : Windows ドメインのユーザー アカウント。例 : DomainName\ProfileName。
Domain Machine : Windows ドメインに参加しているコンピューターで実行されている、コンピューター ID を使用するプロセス。例 : MachineName\Network Service。
![]() |
---|
サービス資格情報は、ServiceHost クラスの Open メソッドが呼び出されたときにキャプチャされます。クライアント資格情報は、クライアントがメッセージを送信するたびに読み取られます。 |
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 Technical Supplement for Windows」を参照してください。
Kerberos プロトコル ダイレクトでは Domain Machine アカウントでサービスを実行する必要がある
この状況は、次のコードに示すように、ClientCredentialType プロパティが Windows に設定され、NegotiateServiceCredential プロパティが false に設定されている場合に発生します。
Dim b As New WSHttpBinding()
' By default, the WSHttpBinding uses Windows authentication
' and Message mode.
b.Security.Message.NegotiateServiceCredential = False
WSHttpBinding b = 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 を実装するには、次の手順を実行します。
AllowedImpersonationLevel を Delegation に設定して委任を実装します。
次のような SSPI ネゴシエーションが必要です。
標準バインディングを使用する場合は、
NegotiateServiceCredential
プロパティを true に設定します。カスタム バインディングを使用する場合は、
Security
要素のAuthenticationMode
属性を SspiNegotiated に設定します。
次のように、NTLM を使用できないようにすることで、SSPI ネゴシエーションで Kerberos を使用する必要があります。
NTLM を使用できないようにするには、コードで
ChannelFactory.Credentials.Windows.AllowNtlm = false
ステートメントを使用します。構成ファイルで
allowNtlm
属性を false に設定することもできます。この属性は、<windows> of <clientCredentials> element に含まれています。
NTLM プロトコル
ネゴシエート SSP は NTLM にフォールバックするが、NTLM が無効になっている
AllowNtlm プロパティを false に設定すると、NTLM が使用されている場合、Windows Communication Foundation (WCF) はベスト エフォートで例外をスローします。このプロパティを false に設定すると、ネットワークで経由で NTLM 資格情報が送信できない可能性があります。
NTLM へのフォールバックを無効にする方法を次に示します。
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.Windows.AllowNtlm = False
CalculatorClient cc = new
CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.Windows.AllowNtlm = false;
NTLM ログオンが失敗する
サービスで、クライアント資格情報が有効ではありません。ユーザー名とパスワードが正しく設定されており、サービスを実行しているコンピューターに認識されているアカウントに対応していることを確認します。NTLM では、指定された資格情報を使用してサービスのコンピューターにログオンします。資格情報がクライアントを実行しているコンピューターで有効であっても、サービスのコンピューターでは有効でない場合、このログオンは失敗します。
匿名 NTLM ログオンが発生するが、既定では匿名ログオンが無効になっている
次の例に示すように、クライアントの作成時に、AllowedImpersonationLevel プロパティを Anonymous に設定します。ただし、既定では、サーバーは匿名ログオンを許可しません。これは、WindowsServiceCredential クラスの AllowAnonymousLogons プロパティの既定値が false であるためです。
匿名ログオンを有効にすることを試みるクライアント コードを次に示します (既定のプロパティは Identification です)。
Dim cc As New CalculatorClient("WSHttpBinding_ICalculator")
cc.ClientCredentials.Windows.AllowedImpersonationLevel = _
System.Security.Principal.TokenImpersonationLevel.Anonymous
CalculatorClient cc =
new CalculatorClient("WSHttpBinding_ICalculator");
cc.ClientCredentials.Windows.AllowedImpersonationLevel =
System.Security.Principal.TokenImpersonationLevel.Anonymous;
サーバーによって匿名ログオンを有効にするように既定値を変更するサービス コードを次に示します。
Dim httpUri As New Uri("https://localhost:8000/")
Dim sh As New ServiceHost(GetType(Calculator), httpUri)
sh.Credentials.WindowsAuthentication.AllowAnonymousLogons = True
Uri httpUri = new Uri("https://localhost:8000/");
ServiceHost sh = new ServiceHost(typeof(Calculator), httpUri);
sh.Credentials.WindowsAuthentication.AllowAnonymousLogons = true;
偽装詳細情報、「WCF の委任と偽装」を参照してください。
もう 1 つの方法として、SYSTEM ビルトイン アカウントを使用する Windows サービスとしてクライアントを実行します。
その他の問題
クライアント資格情報が正しく設定されていない
Windows 認証では、UserNamePasswordClientCredential ではなく、ClientBase クラスの ClientCredentials プロパティによって返された WindowsClientCredential インスタンスを使用します。誤りのあるコード例を次に示します。
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");
cc.ClientCredentials.UserName.UserName = GetUserName(); // wrong!
cc.ClientCredentials.UserName.Password = GetPassword(); // wrong!
正しいコード例を次に示します。
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()
CalculatorClient cc = 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 とドメイン コントローラーを使用するため、このサービスを認証できなくなります。
参照
リファレンス
WindowsClientCredential
WindowsServiceCredential
WindowsClientCredential
ClientBase