Поделиться через


Безопасность сообщений с использованием клиента Windows без согласования учетных данных

В следующем сценарии показан клиент и служба Windows Communication Foundation (WCF), защищенные протоколом Kerberos.

Клиент и служба находятся в одном и том же домене или в доверенных доменах.

Примечание.

Разница между этим сценарием и безопасностью сообщений с клиентом Windows заключается в том, что этот сценарий не согласовывает учетные данные службы со службой до отправки сообщения приложения. И так как для этого требуется протокол Kerberos, для этого сценария необходима среда домена Windows.

Безопасность сообщений без согласования учетных данных

Characteristic Description
Режим безопасности Сообщение
Совместимость Да, WS-Security с клиентами, совместимыми с профилем маркера Kerberos
Проверка подлинности (сервера) Взаимная проверка подлинности сервера и клиента
Проверка подлинности (клиента) Взаимная проверка подлинности сервера и клиента
Целостность Да
Конфиденциальность Да
Транспорт HTTP
Привязка WSHttpBinding

Service

Предполагается, что представленные ниже код и конфигурация выполняются независимо. Выполните одно из следующих действий:

  • Создайте автономную службу, используя код без конфигурации.

  • Создайте службу, используя предоставленную конфигурацию, но не определяйте конечные точки.

Код

В следующем коде создается конечная точка службы, которая использует безопасность сообщений. Этот код отключает согласование учетных данных службы и установку маркера контекста безопасности (SCT).

Примечание.

Для использования типа учетных данных Windows без согласования учетная запись пользователя службы должна иметь доступ к имени участника-службы (SPN), зарегистрированному с доменом Active Directory. Это можно сделать двумя способами.

  1. Используйте учетную запись NetworkService или LocalSystem для запуска службы. Так как эти учетные записи имеют доступ к имени субъекта-службы компьютера, который устанавливается при присоединении компьютера к домену Active Directory, WCF автоматически создает соответствующий элемент SPN в конечной точке службы в метаданных службы (язык описания веб-служб или WSDL).

  2. Запустите службу из любой учетной записи домена Active Directory. В этом случае потребуется установить SPN для учетной записи домена. Это можно сделать, например, с помощью средства Setspn.exe. После создания имени субъекта-службы для учетной записи службы настройте WCF для публикации этого имени участника-службы клиентам службы через его метаданные (WSDL). Это можно сделать, настроив удостоверение конечной точки для предоставляемой конечной точки либо в файле конфигурации приложения, либо в коде. В следующем примере описывается программный способ публикации удостоверения.

Дополнительные сведения о субъекта-службы, протоколе Kerberos и Active Directory см . в техническом дополнение Kerberos для Windows. Дополнительные сведения о удостоверениях конечных точек см. в разделе "Режимы проверки подлинности 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>

Клиент

Предполагается, что представленные ниже код и конфигурация выполняются независимо. Выполните одно из следующих действий:

  • Создайте автономный клиент, используя код (и код клиента).

  • Создайте клиент, который не определяет никаких адресов конечных точек. Вместо этого используйте конструктор клиента, который принимает в качестве аргумента имя конфигурации. Например:

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

Код

Следующий код служит для настройки клиента. Для режима безопасности задано значение Message, типу учетных данных клиента присвоено значение Windows. Обратите внимание: свойствам NegotiateServiceCredential и EstablishSecurityContext задается значение false.

Примечание.

Для использования типа учетных данных Windows без согласования требуется настроить SPN учетной записи службы до начала обмена данными со службой. Клиент использует имя SPN, чтобы получить маркер Kerberos для проверки подлинности и обеспечения безопасности обмена данными со службой. В следующем образце показано, как настроить SPN службы для клиента. Если вы используете средство служебной программы метаданных ServiceModel (Svcutil.exe) для создания клиента, имя субъекта-службы будет автоматически распространяться на клиент из метаданных службы (WSDL), если метаданные службы содержат эти сведения. Дополнительные сведения о настройке службы для включения имени участника-службы в метаданные службы см. в разделе "Служба" далее в этом разделе.

Дополнительные сведения о spNs, Kerberos и Active Directory см . в техническом дополнение Kerberos для Windows. Дополнительные сведения о удостоверениях конечных точек см. в разделе "Режимы проверки подлинности 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.

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

См. также