Udostępnij za pośrednictwem


Zabezpieczanie komunikatów za pomocą klienta systemu Windows bez negocjowania poświadczeń

W poniższym scenariuszu przedstawiono klienta i usługę programu Windows Communication Foundation (WCF) zabezpieczoną przez protokół Kerberos.

Zarówno usługa, jak i klient znajdują się w tej samej domenie lub domenach zaufanych.

Uwaga

Różnica między tym scenariuszem a zabezpieczeniami komunikatów z klientem systemu Windows polega na tym, że ten scenariusz nie negocjuje poświadczeń usługi z usługą przed wysłaniem komunikatu aplikacji. Ponadto, ponieważ wymaga to protokołu Kerberos, ten scenariusz wymaga środowiska domeny systemu Windows.

Zabezpieczenia komunikatów bez negocjacji poświadczeń

Characteristic opis
Tryb zabezpieczeń Komunikat
Współdziałanie Tak, zabezpieczenia WS z klientami zgodnymi z profilem tokenu Kerberos
Uwierzytelnianie (serwer) Wzajemne uwierzytelnianie serwera i klienta
Uwierzytelnianie (klient) Wzajemne uwierzytelnianie serwera i klienta
Integralność Tak
Poufność Tak
Transport HTTP
Wiązanie WSHttpBinding

Usługa

Poniższy kod i konfiguracja mają być uruchamiane niezależnie. Wykonaj jedną z następujących czynności:

  • Utwórz autonomiczną usługę przy użyciu kodu bez konfiguracji.

  • Utwórz usługę przy użyciu podanej konfiguracji, ale nie zdefiniuj żadnych punktów końcowych.

Kod

Poniższy kod tworzy punkt końcowy usługi, który korzysta z zabezpieczeń komunikatów. Kod wyłącza negocjacje poświadczeń usługi i utworzenie tokenu kontekstu zabezpieczeń (SCT).

Uwaga

Aby użyć typu poświadczeń systemu Windows bez negocjacji, konto użytkownika usługi musi mieć dostęp do głównej nazwy usługi (SPN), która jest zarejestrowana w domenie usługi Active Directory. Można to zrobić na dwa sposoby:

  1. NetworkService Użyj konta lubLocalSystem, aby uruchomić usługę. Ponieważ te konta mają dostęp do nazwy SPN maszyny, która jest ustanawiana podczas dołączania maszyny do domeny usługi Active Directory, program WCF automatycznie generuje odpowiedni element NAZWY SPN wewnątrz punktu końcowego usługi w metadanych usługi (Język opisu usług sieci Web lub WSDL).

  2. Użyj dowolnego konta domeny usługi Active Directory, aby uruchomić usługę. W takim przypadku należy ustanowić nazwę SPN dla tego konta domeny. Jednym ze sposobów jest użycie narzędzia Setspn.exe. Po utworzeniu nazwy SPN dla konta usługi skonfiguruj usługę WCF, aby opublikować nazwę SPN na klientach usługi za pośrednictwem metadanych (WSDL). Odbywa się to przez ustawienie tożsamości punktu końcowego dla uwidocznionego punktu końcowego, choć plik konfiguracji aplikacji lub kod. Poniższy przykład programowo publikuje tożsamość.

Aby uzyskać więcej informacji na temat nazw SPN, protokołu Kerberos i usługi Active Directory, zobacz Dodatek techniczny protokołu Kerberos dla systemu Windows. Aby uzyskać więcej informacji na temat tożsamości punktów końcowych, zobacz SecurityBindingElement Authentication Modes (Tryby uwierzytelniania 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()

Konfigurowanie

Zamiast kodu można użyć następującej konfiguracji.

<?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>

Klient

Poniższy kod i konfiguracja mają być uruchamiane niezależnie. Wykonaj jedną z następujących czynności:

  • Utwórz klienta autonomicznego przy użyciu kodu (i kodu klienta).

  • Utwórz klienta, który nie definiuje żadnych adresów punktów końcowych. Zamiast tego użyj konstruktora klienta, który przyjmuje nazwę konfiguracji jako argument. Na przykład:

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

Kod

Poniższy kod konfiguruje klienta. Tryb zabezpieczeń jest ustawiony na Komunikat, a typ poświadczeń klienta jest ustawiony na Windows. Należy pamiętać, że NegotiateServiceCredential właściwości i EstablishSecurityContext są ustawione na false.

Uwaga

Aby można było używać typu poświadczeń systemu Windows bez negocjacji, należy skonfigurować klienta z nazwą SPN konta usługi przed rozpoczęciem komunikacji z usługą. Klient używa nazwy SPN do uzyskania tokenu Kerberos w celu uwierzytelnienia i zabezpieczenia komunikacji z usługą. W poniższym przykładzie pokazano, jak skonfigurować klienta przy użyciu nazwy SPN usługi. Jeśli używasz narzędzia ServiceModel Metadata Tool (Svcutil.exe) do wygenerowania klienta, nazwa SPN usługi zostanie automatycznie rozpropagowana do klienta z metadanych usługi (WSDL), jeśli metadane usługi zawierają te informacje. Aby uzyskać więcej informacji na temat sposobu konfigurowania usługi w celu uwzględnienia nazwy SPN w metadanych usługi, zobacz sekcję "Usługa" w dalszej części tego tematu.

Aby uzyskać więcej informacji na temat nazw SPN, Kerberos i Active Directory, zobacz Dodatek techniczny protokołu Kerberos dla systemu Windows. Aby uzyskać więcej informacji na temat tożsamości punktów końcowych, zobacz SecurityBindingElement Authentication Modes (Tryby uwierzytelniania 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

Konfigurowanie

Poniższy kod konfiguruje klienta. Należy pamiętać, że <element servicePrincipalName> musi być ustawiony tak, aby był zgodny z nazwą SPN usługi zarejestrowaną dla konta usługi w domenie usługi Active Directory.

<?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>

Zobacz też