IIS でホストされる多くの WCF サービスを開発しています。(Windows Server 2003 SP2 で実行されている IIS 6.0)。これらのサービスは REST 用に設定されています。環境 (DEV、CERT、PROD) の場合、通常、IIS サーバーごとに多くのサービスがあります。各サービスには、アプリケーション プールを介して割り当てられる独自のログイン アカウントがあります。
これは正常に機能しますが、仮想ディレクトリで Windows 認証を有効にすると (偽装や委任ではなく、ユーザー コンテキストの受け渡しを許可するため)、特定のケースでセキュリティ エラーが発生します。ServiceEndpoint を使用して C# コードでサービスに接続すると機能しますが、ブラウザーまたは非 Wcf コード (HttpWebRequest、java など) を介してサービスに接続すると、セキュリティ エラーが発生します。
IIS の認証を Negotiate, NTLM から NTLM のみに変更すると、機能します。実際に起こっていることは、Kerberos を無効にすることです。これらのサービスはネットワーク内の他のサーバーと通信するため、サービスがリモート サーバー (通常は SQL サーバー) に接続できないという別の問題が発生し始めます。
ここで奇妙な部分があります。マシンに DNS エイリアス (CNAME レコード) を与え、URL をエイリアスと共に使用すると、機能します。例えば
http://dnsalias/service/myservice.svc/foo WORKS!
but
http://machinename/service/myservice.svc/foo FAILS :(
これらすべてのマシンに DNS エイリアスを割り当てることはできません (これまではこれが解決策でした)。これは、VM を広範囲に使用し始め、それらを回転させたり回転させたりするためです。マシン名しかないので、マシンの起動時に DNS エイリアスのスクリプト作成を開始したくありません。
SPN の問題はわかりましたが、同じ Web サイト (通常は既定の Web サイト) で複数のサービスがホストされているため、サーバー/アカウントごとに 1 つのサービス プリンシパル名しか作成できません。サーバーごとに複数のサービスをホストしており、それぞれが独自のアカウントにマップされているため、これは解決策ではありません。
setspn -a HTTP//WCFServer.domain.com customDomainAccount
別のしわがあります。構成ファイルではエンドポイントを定義せず、コードでのみ定義します。REST バインディングを取得するコードは次のとおりです。
protected internal static Binding GetWebHttpBinding()
{
// Create a new binding with Authentication enabled
var binding = new WebHttpBinding(WebHttpSecurityMode.TransportCredentialOnly);
// Set defaults
SetTimeouts(binding);
SetReaderQuotas(binding.ReaderQuotas);
binding.MaxReceivedMessageSize = MaxReceivedMessageSize;
binding.MaxBufferSize = 65536;
// Set the Credential type to Windows to allow single sign-on
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Windows;
// Need Streamed Response since Transport security does not allow streamed requests
binding.TransferMode = TransferMode.StreamedResponse;
return binding;
}