資格情報ネゴシエーションを使用しない Windows クライアントを使用するメッセージ セキュリティ

次のシナリオは、Kerberos プロトコルによって保護される Windows Communication Foundation (WCF) のクライアントとサービスを示します。

サービスとクライアントは、いずれも同じドメインまたは信頼できるドメインに配置されています。

Note

Windows クライアントを使用するメッセージ セキュリティとは異なり、このシナリオでは、アプリケーション メッセージを送信する前にサービスの資格情報をサービスとネゴシエートしません。 また、このシナリオでは Kerberos プロトコルを使用するので、Windows ドメイン環境が必要になります。

資格情報ネゴシエーションを使用しないメッセージのセキュリティ

特徴 説明
セキュリティ モード メッセージ
相互運用性 ○ Kerberos トークン プロファイル互換クライアントを使用する WS-Security
認証 (サーバー) サーバーとクライアントの相互認証
認証 (クライアント) サーバーとクライアントの相互認証
整合性 はい
機密性 はい
トランスポート HTTP
バインド WSHttpBinding

サービス

次のコードと構成は、別々に実行します。 次のいずれかの操作を行います。

  • 構成を使用せずに、コードを使用してスタンドアロン サービスを作成します。

  • 提供された構成を使用してサービスを作成しますが、エンドポイントを定義しません。

コード

次のコードは、メッセージ セキュリティを使用するサービス エンドポイントを作成します。 このコードは、サービス資格情報のネゴシエーションとセキュリティ コンテキスト トークン (SCT) の確立を無効にします。

Note

ネゴシエートせずに Windows の資格情報を使用するには、サービスのユーザー アカウントが、Active Directory ドメインを使用して登録されたサービス プリンシパル名 (SPN) にアクセスする必要があります。 次の 2 つの方法で行います。

  1. NetworkService アカウントまたは LocalSystem アカウントを使用してサービスを実行します。 これらのアカウントでは、マシンが Active Directory ドメインに参加したときに確立されたマシンの SPN にアクセスできるため、WCF ではサービスのメタデータ (Web サービス記述言語 (WSDL)) にあるサービスのエンドポイント内部に適切な SPN 要素が自動的に生成されます。

  2. 任意の Active Directory ドメイン アカウントを使用してサービスを実行します。 この場合、そのドメイン アカウント用の SPN を確立する必要があります。 これを行うには、Setspn.exe ユーティリティ ツールを使用する方法があります。 サービスのアカウント用の SPN を作成したら、SPN をそのメタデータ (WSDL) を通じてサービスのクライアントに公開するように WCF を構成します。 これを行うには、アプリケーション構成ファイルまたはコードのどちらかを使用して、公開されるエンドポイントのエンドポイント ID を設定します。 プログラムで ID を公開する方法を次の例に示します。

SPN、Kerberos プロトコル、および Active Directory の詳細については、「Windows に対する Kerberos のテクニカル サポート」を参照してください。 エンドポイントID の詳細については、「SecurityBindingElement 認証モード」を参照してください。

// Create the service host.
ServiceHost myServiceHost = new ServiceHost(typeof(Calculator));

// Create the binding.
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.ClientCredentialType =
     MessageCredentialType.Windows;

// Disable credential negotiation and establishment of the
// security context.
binding.Security.Message.NegotiateServiceCredential = false;
binding.Security.Message.EstablishSecurityContext = false;

// Create a URI for the endpoint address.
Uri httpUri = new Uri("http://localhost/Calculator");

// Create the EndpointAddress with the SPN for the Identity.
EndpointAddress ea = new EndpointAddress(httpUri,
    EndpointIdentity.CreateSpnIdentity("service_spn_name"));

// Get the contract from the ICalculator interface (not shown here).
// See the sample applications for an example of the ICalculator.
ContractDescription contract = ContractDescription.GetContract(
    typeof(ICalculator));

// Create a new ServiceEndpoint.
ServiceEndpoint se = new ServiceEndpoint(contract, binding, ea);

// Add the service endpoint to the service.
myServiceHost.Description.Endpoints.Add(se);

// Open the service.
myServiceHost.Open();
Console.WriteLine("Listening...");
Console.ReadLine();

// Close the service.
myServiceHost.Close();
' Create the service host.
Dim myServiceHost As New ServiceHost(GetType(ServiceModel.Calculator))

' Create the binding.
Dim binding As New WSHttpBinding()
binding.Security.Mode = SecurityMode.Message
binding.Security.Message.ClientCredentialType = _
   MessageCredentialType.Windows

' Disable credential negotiation and establishment of the
' security context.
binding.Security.Message.NegotiateServiceCredential = False
binding.Security.Message.EstablishSecurityContext = False

' Create a URI for the endpoint address.
Dim httpUri As New Uri("http://localhost/Calculator")

' Create the EndpointAddress with the SPN for the Identity.
Dim ea As New EndpointAddress(httpUri, _
EndpointIdentity.CreateSpnIdentity("service_spn_name"))

' Get the contract from the ICalculator interface (not shown here).
' See the sample applications for an example of the ICalculator.
Dim contract As ContractDescription = ContractDescription.GetContract(GetType(ICalculator))

' Create a new ServiceEndpoint.
Dim se As New ServiceEndpoint(contract, binding, ea)

' Add the service endpoint to the service.
myServiceHost.Description.Endpoints.Add(se)

' Open the service.
myServiceHost.Open()
Console.WriteLine("Listening...")
Console.ReadLine()

' Close the service.
myServiceHost.Close()

構成

コードの代わりに次の構成を使用できます。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <behaviors />
    <services>
      <service behaviorConfiguration="" name="ServiceModel.Calculator">
        <endpoint address="http://localhost/Calculator"
                  binding="wsHttpBinding"
                  bindingConfiguration="KerberosBinding"
                  name="WSHttpBinding_ICalculator"
                  contract="ServiceModel.ICalculator"
                  listenUri="net.tcp://localhost/metadata" >
         <identity>
            <servicePrincipalName value="service_spn_name" />
         </identity>
        </endpoint>
      </service>
    </services>
    <bindings>
      <wsHttpBinding>
        <binding name="KerberosBinding">
          <security>
            <message negotiateServiceCredential="false"
                     establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client />
  </system.serviceModel>
</configuration>

Client

次のコードと構成は、別々に実行します。 次のいずれかの操作を行います。

  • コード (およびクライアント コード) を使用してスタンドアロン クライアントを作成します。

  • エンドポイント アドレスを定義しないクライアントを作成します。 代わりに、引数として構成名を受け取るクライアント コンストラクターを使用します。 次に例を示します。

    CalculatorClient cc = new CalculatorClient("EndpointConfigurationName");
    
    Dim cc As New CalculatorClient("EndpointConfigurationName")
    

コード

クライアントを構成する場合のコード例を次に示します。 セキュリティ モードは Message に設定され、クライアント資格情報の種類は Windows に設定されています。 NegotiateServiceCredential プロパティと EstablishSecurityContext プロパティには、false が設定されていることに注意してください。

Note

ネゴシエートせずに Windows の資格情報を使用するには、サービスとの通信を開始する前に、サービスのアカウントの SPN を使用してクライアントを構成する必要があります。 クライアントは SPN を使用して Kerberos トークンを取得し、サービスとの通信を認証し保護します。 サービスの SPN を使用してクライアントを構成する方法を次の例に示します。 ServiceModel メタデータ ユーティリティ ツール (Svcutil.exe) を使用してクライアントを生成する場合に、サービスのメタデータ (WSDL) にサービスの SPN 情報が含まれていれば、サービスのメタデータからその SPN が自動的にクライアントに伝達されます。 サービスのメタデータにその SPN を含めるようにサービスを構成する方法の詳細については、このトピックの後続セクションの「サービス」を参照してください。

SPN、Kerberos、および Active Directory の詳細については、「Windows に対する Kerberos のテクニカル サポート」を参照してください。 エンドポイントID の詳細については、「SecurityBindingElement 認証モード」のトピックを参照してください。

// Create the binding.
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Message;
myBinding.Security.Message.ClientCredentialType =
    MessageCredentialType.Windows;

// Disable credential negotiation and the establishment of
// a security context.
myBinding.Security.Message.NegotiateServiceCredential = false;
myBinding.Security.Message.EstablishSecurityContext = false;

// Create the endpoint address and set the SPN identity.
// The SPN must match the identity of the service's SPN.
// If using SvcUtil to generate a configuration file, the SPN
// will be published as the <servicePrincipalName> element under the
// <identity> element.
EndpointAddress ea = new EndpointAddress(
new Uri("http://machineName/Calculator"),
EndpointIdentity.CreateSpnIdentity("service_spn_name"));

// Create the client.
CalculatorClient cc =
    new CalculatorClient(myBinding, ea);

// Begin using the client.

try
{
    cc.Open();
    Console.WriteLine(cc.Add(200, 1111));
    Console.ReadLine();

    // Close the client.
    cc.Close();
}
' Create the binding.
Dim myBinding As New WSHttpBinding()
myBinding.Security.Mode = SecurityMode.Message
myBinding.Security.Message.ClientCredentialType = _
   MessageCredentialType.Windows

' Disable credential negotiation and the establishment of
' a security context.
myBinding.Security.Message.NegotiateServiceCredential = False
myBinding.Security.Message.EstablishSecurityContext = False

' Create the endpoint address and set the SPN identity.
' The SPN must match the identity of the service's SPN.
' If using SvcUtil to generate a configuration file, the SPN
' will be published as the <servicePrincipalName> element under the
' <identity> element.
Dim ea As New EndpointAddress(New Uri("http://machineName/calculator"), _
EndpointIdentity.CreateSpnIdentity("service_spn_name"))

' Create the client.
Dim cc As New CalculatorClient(myBinding, ea)

' Begin using the client.
Try
    cc.Open()

    Console.WriteLine(cc.Add(100, 11))
    Console.ReadLine()

    ' Close the client.
    cc.Close()
Catch tex As TimeoutException
    Console.WriteLine(tex.Message)
    cc.Abort()
Catch cex As CommunicationException
    Console.WriteLine(cex.Message)
    cc.Abort()
Finally
    Console.WriteLine("Closed the client")
    Console.ReadLine()
End Try

構成

クライアントを構成する場合のコード例を次に示します。 <servicePrincipalName> 要素は、Active Directory ドメイン内でサービスのアカウント用に登録されたサービスの SPN と一致するように設定する必要があります。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.serviceModel>
    <bindings>
      <wsHttpBinding>
        <binding name="WSHttpBinding_ICalculator" >
          <security mode="Message">
            <message clientCredentialType="Windows"
                     negotiateServiceCredential="false"
                     establishSecurityContext="false" />
          </security>
        </binding>
      </wsHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost/Calculator"
                binding="wsHttpBinding"
                bindingConfiguration="WSHttpBinding_ICalculator"
                contract="ICalculator"
                name="WSHttpBinding_ICalculator">
        <identity>
          <servicePrincipalName value="service_spn_name" />
        </identity>
      </endpoint>
    </client>
  </system.serviceModel>
</configuration>

関連項目