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


Доверенная подсистема

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

Trusted subsystem

Показанный на рисунке процесс доверенной подсистемы пошагово описан ниже.

  1. Клиент отправляет запрос (вместе с учетными данными) доверенной подсистеме.

  2. Доверенная подсистема проверяет подлинность пользователя и авторизует его.

  3. Доверенная подсистема отправляет сообщение запроса удаленному ресурсу. Этот запрос сопровождается учетными данными доверенной подсистемы (или учетной записи службы, от имени которой выполняется процесс доверенной подсистемы).

  4. Внутренний ресурс проверяет подлинность доверенной подсистемы и авторизует ее. Затем он обрабатывает запрос и отправляет ответ доверенной подсистеме.

  5. Доверенная подсистема обрабатывает ответ и отправляет свой ответ клиенту.

Characteristic Description
Режим безопасности Сообщение
Совместимость Только Windows Communication Foundation (WCF).
Проверка подлинности (служба) Служба маркеров безопасности проверяет подлинность клиентов и авторизует их.
Проверка подлинности (клиент) Доверенная подсистема проверяет подлинность клиента, а ресурс проверяет подлинность службы доверенной подсистемы.
Целостность Да
Конфиденциальность Да
Транспорт HTTP между клиентом и службой доверенной подсистемы.

NET.TCP между службой доверенной подсистемы и ресурсом (внутренней службой).
Привязка WSHttpBinding и NetTcpBinding<wsFederationHttpBinding>

Ресурс (внутренняя служба)

Код

В следующем коде показано, как создать конечную точку службы для ресурса, работающую в режиме безопасности транспорта по транспортному протоколу TCP.

// Create a ServiceHost for the CalculatorService type and provide the base address.
using (ServiceHost host = new ServiceHost(typeof(BackendService)))
{
    BindingElementCollection bindingElements = new BindingElementCollection();
    bindingElements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement());
    bindingElements.Add(new WindowsStreamSecurityBindingElement());
    bindingElements.Add(new TcpTransportBindingElement());
    CustomBinding backendServiceBinding = new CustomBinding(bindingElements);

    host.AddServiceEndpoint(typeof(ICalculator), backendServiceBinding, "BackendService");

    // Open the ServiceHostBase to create listeners and start listening for messages.
    host.Open();

    // The service can now be accessed.
    Console.WriteLine("The service is ready.");
    Console.WriteLine("Press <ENTER> to terminate service.");
    Console.WriteLine();
    Console.ReadLine();
    host.Close();
}
' Create a ServiceHost for the CalculatorService type and provide the base address.
Using host As New ServiceHost(GetType(BackendService), New Uri("net.tcp://localhost:8001/BackendService"))

    Dim bindingElements As New BindingElementCollection()
    bindingElements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement())
    bindingElements.Add(New WindowsStreamSecurityBindingElement())
    bindingElements.Add(New TcpTransportBindingElement())
    Dim backendServiceBinding As New CustomBinding(bindingElements)

    host.AddServiceEndpoint(GetType(ICalculator), backendServiceBinding, "BackendService")

    ' Open the ServiceHostBase to create listeners and start listening for messages.
    host.Open()

    ' The service can now be accessed.
    Console.WriteLine("The service is ready.")
    Console.WriteLine("Press <ENTER> to terminate service.")
    Console.WriteLine()
    Console.ReadLine()
    host.Close()
End Using

Настройка

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

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  
  <system.serviceModel>  
    <services>  
      <service name="Microsoft.ServiceModel.Samples.BackendService"  
               behaviorConfiguration="BackendServiceBehavior">  
        <endpoint address="net.tcp://localhost.com:8001/BackendService"  
                  binding="customBinding"  
                  bindingConfiguration="Binding1"  
                  contract="Microsoft.ServiceModel.Samples.ICalculator"/>  
      </service>  
    </services>  
    <bindings>  
      <customBinding>  
        <binding name="Binding1">  
          <security authenticationMode="UserNameOverTransport"/>  
          <windowsStreamSecurity/>  
          <tcpTransport/>  
        </binding>  
      </customBinding>  
    </bindings>  
    <behaviors>  
      <serviceBehaviors>  
        <behavior name="BackendServiceBehavior">  
          <serviceCredentials>  
            <userNameAuthentication userNamePasswordValidationMode="Custom"  
                                    customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator, BackendService"/>  
          </serviceCredentials>  
        </behavior>  
      </serviceBehaviors>  
    </behaviors>  
  </system.serviceModel>  
</configuration>  

Доверенная подсистема

Код

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

Uri baseAddress = new Uri("http://localhost:8000/FacadeService");
using (ServiceHost myServiceHost = new ServiceHost(typeof(CalculatorService), baseAddress))
{
    WSHttpBinding binding = new WSHttpBinding();
    binding.Security.Mode = SecurityMode.Message;
    binding.Security.Message.ClientCredentialType =
        MessageCredentialType.UserName;
    myServiceHost.AddServiceEndpoint(typeof(CalculatorService), binding, string.Empty);
    myServiceHost.Open();
    // Wait for calls.
    myServiceHost.Close();
}
Dim baseAddress As New Uri("http://localhost:8000/FacadeService")
Using myServiceHost As New ServiceHost(GetType(CalculatorService), baseAddress)
    Dim binding As New WSHttpBinding()
    binding.Security.Mode = SecurityMode.Message
    binding.Security.Message.ClientCredentialType = MessageCredentialType.UserName
    myServiceHost.AddServiceEndpoint(GetType(CalculatorService), binding, String.Empty)
    myServiceHost.Open()
    ' Wait for calls. 
    myServiceHost.Close()
End Using

В следующем коде показана служба в доверенной подсистеме, которая обменивается данными с внутренней службой в режиме безопасности транспорта по транспортному протоколу TCP.

public double Multiply(double n1, double n2)
{
    // Create the binding.
    BindingElementCollection bindingElements = new BindingElementCollection();
    bindingElements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement());
    bindingElements.Add(new WindowsStreamSecurityBindingElement());
    bindingElements.Add(new TcpTransportBindingElement());
    CustomBinding backendServiceBinding = new CustomBinding(bindingElements);

    // Create the endpoint address.
    EndpointAddress ea = new
        EndpointAddress("http://contoso.com:8001/BackendService");

    // Call the back-end service.
    CalculatorClient client = new CalculatorClient(backendServiceBinding, ea);
    client.ClientCredentials.UserName.UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name;
    double result = client.Multiply(n1, n2);
    client.Close();

    return result;
}
Public Function Multiply(ByVal n1 As Double, ByVal n2 As Double) As Double _
    Implements ICalculator.Multiply
    ' Create the binding.
    Dim bindingElements As New BindingElementCollection()
    bindingElements.Add(SecurityBindingElement.CreateUserNameOverTransportBindingElement())
    bindingElements.Add(New WindowsStreamSecurityBindingElement())
    bindingElements.Add(New TcpTransportBindingElement())
    Dim backendServiceBinding As New CustomBinding(bindingElements)

    ' Create the endpoint address. 
    Dim ea As New EndpointAddress("http://contoso.com:8001/BackendService")

    ' Call the back-end service.
    Dim client As New CalculatorClient(backendServiceBinding, ea)
    client.ClientCredentials.UserName.UserName = ServiceSecurityContext.Current.PrimaryIdentity.Name
    Dim result As Double = client.Multiply(n1, n2)
    client.Close()

    Return result
End Function

Настройка

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

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  
  <system.serviceModel>  
    <services>  
      <service name="Microsoft.ServiceModel.Samples.FacadeService"  
               behaviorConfiguration="FacadeServiceBehavior">  
        <host>  
          <baseAddresses>  
            <add baseAddress="http://localhost:8000/FacadeService"/>  
          </baseAddresses>  
        </host>  
        <endpoint address="http://localhost:8000/FacadeService"  
                  binding="wsHttpBinding"  
                  bindingConfiguration="Binding1"  
                  contract="Microsoft.ServiceModel.Samples.ICalculator"/>  
      </service>  
    </services>  
    <client>  
      <endpoint name=""
                address="net.tcp://contoso.com:8001/BackendService"  
                binding="customBinding"  
                bindingConfiguration="ClientBinding"  
                contract="Microsoft.ServiceModel.Samples.ICalculator"/>  
    </client>  
    <bindings>  
      <wsHttpBinding>  
        <binding name="Binding1">  
          <security mode="Message">  
            <message clientCredentialType="UserName"/>  
          </security>  
        </binding>  
      </wsHttpBinding>  
      <customBinding>  
        <binding name="ClientBinding">  
          <security authenticationMode="UserNameOverTransport"/>  
          <windowsStreamSecurity/>  
          <tcpTransport/>  
        </binding>  
      </customBinding>  
    </bindings>  
    <behaviors>  
      <serviceBehaviors>  
        <behavior name="FacadeServiceBehavior">  
          <serviceMetadata httpGetEnabled="True"/>  
          <serviceCredentials>  
            <serviceCertificate findValue="Contoso.com"  
                                storeLocation="LocalMachine"  
                                storeName="My"  
                                x509FindType="FindBySubjectName" />  
            <userNameAuthentication userNamePasswordValidationMode="Custom"  
                                    customUserNamePasswordValidatorType="Microsoft.ServiceModel.Samples.MyUserNamePasswordValidator, FacadeService"/>  
          </serviceCredentials>  
        </behavior>  
      </serviceBehaviors>  
    </behaviors>  
  </system.serviceModel>  
</configuration>  

Клиент

Код

В следующем коде показано, как создать клиент, обменивающийся данными с доверенной подсистемой в режиме безопасности сообщения по протоколу HTTP и использующий для проверки подлинности имя пользователя и пароль.

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

// Create the endpoint address.
EndpointAddress ea = new
    EndpointAddress("http://www.cohowinery.com:8000/FacadeService");

CalculatorClient client = new CalculatorClient(subsystemBinding, ea);

// Configure client with valid machine or domain account (username,password)
client.ClientCredentials.UserName.UserName = username;
client.ClientCredentials.UserName.Password = password.ToString();

// Call the Multiply service operation.
double value1 = 39D;
double value2 = 50.44D;
double result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);

//Closing the client gracefully closes the connection and cleans up resources
client.Close();
' Create the binding.
Dim subsystemBinding As New WSHttpBinding()
subsystemBinding.Security.Mode = SecurityMode.Message
subsystemBinding.Security.Message.ClientCredentialType = MessageCredentialType.UserName

' Create the URI for the endpoint.
Dim ea As New EndpointAddress("http://www.cohowinery.com:8000/FacadeService")

Dim client As New CalculatorClient(subsystemBinding, ea)

' Configure client with valid machine or domain account (username,password)
client.ClientCredentials.UserName.UserName = username
client.ClientCredentials.UserName.Password = password.ToString()

' Call the Multiply service operation.
Dim value1 As Double = 39
Dim value2 As Double = 50.44
Dim result As Double = client.Multiply(value1, value2)
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result)


'Closing the client gracefully closes the connection and cleans up resources
client.Close()

Настройка

Следующий код служит для настройки клиента для использования режима безопасности сообщений по протоколу HTTP, а также имени пользователя и пароля для проверки подлинности. Указать имя пользователя и пароль можно только с помощью кода (они не подлежат настройке).

<?xml version="1.0" encoding="utf-8" ?>  
<configuration>  
  <system.serviceModel>  
    <client>  
        <endpoint name=""
                  address="http://www.cohowinery.com:8000/FacadeService"  
                  binding="wsHttpBinding"  
                  bindingConfiguration="Binding1"  
                  behaviorConfiguration="ClientUserNameBehavior"  
                  contract="Microsoft.ServiceModel.Samples.ICalculator"/>  
    </client>  
    <bindings>  
      <wsHttpBinding>  
        <binding name="Binding1">  
          <security mode="Message">  
            <message clientCredentialType="UserName"/>  
          </security>  
        </binding>  
      </wsHttpBinding>  
    </bindings>  
    <behaviors>  
      <endpointBehaviors>  
        <behavior name="ClientUserNameBehavior">  
          <clientCredentials>  
            <serviceCertificate>  
              <authentication certificateValidationMode="PeerOrChainTrust"/>  
            </serviceCertificate>  
          </clientCredentials>  
        </behavior>  
      </endpointBehaviors>  
    </behaviors>  
  </system.serviceModel>  
</configuration>  

См. также