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


Безопасность сообщений при использовании очереди сообщений

В этом образце показано, как реализовать приложение, использующее протокол WS-Security и проверку подлинности с использованием сертификата X.509v3 для клиента и требующее проверки подлинности сервера с использованием сертификата X.509v3 сервера через MSMQ. В некоторых случаях безопасность сообщений применяется, чтобы гарантировать, что сообщения в хранилище MSMQ остаются зашифрованными, а приложение может осуществлять собственную проверку подлинности сообщений.

Этот образце основан на примере Привязка MSMQ с поддержкой транзакций. Сообщения шифруются и подписываются.

Настройка, построение и выполнение образца

  1. Убедитесь, что выполнена процедура, описанная в разделе Процедура однократной настройки образцов Windows Communication Foundation.

  2. При первом запуске служба проверит наличие очереди. Если очередь отсутствует, служба ее создаст. Можно сначала запустить службу, чтобы создать очередь, либо создать ее с помощью диспетчера очередей MSMQ. Чтобы создать очередь в Windows 2008, выполните следующие шаги.

    1. Откройте диспетчер сервера в Visual Studio 2010.

    2. Разверните вкладку Функции.

    3. Щелкните правой кнопкой мыши узел Очереди личных сообщений и выберите пункты Создать, Частная очередь.

    4. Установите флажок Транзакционная.

    5. В качестве имени новой очереди укажите ServiceModelSamplesTransacted.

  3. Чтобы создать выпуск решения на языке C# или Visual Basic .NET, следуйте инструкциям в разделе Построение образцов Windows Communication Foundation.

Запуск образца на одном компьютере

  1. Убедитесь, что путь включает папку, в которой содержатся файлы Makecert.exe и FindPrivateKey.exe.

  2. Запустите файл Setup.bat из папки установки образца. При этом устанавливаются все сертификаты, необходимые для запуска образца.

    Aa395200.note(ru-ru,VS.100).gifПримечание
    После завершения работы образца выполните в папке образца файл Cleanup.bat, чтобы удалить сертификаты. В других образцах обеспечения безопасности используются те же сертификаты.

  3. Запустите программу Service.exe из каталога \service\bin.

  4. Запустите программу Client.exe из каталога \client\bin. Действия клиента отображаются в консольном приложении клиента.

  5. Если клиенту и службе не удается взаимодействовать, см. раздел Troubleshooting Tips.

Запуск образца на нескольких компьютерах

  1. Скопируйте файлы Setup.bat, Cleanup.bat и ImportClientCert.bat на компьютер службы.

  2. Создайте на клиентском компьютере каталог для двоичных файлов клиента.

  3. Скопируйте в клиентский каталог на клиентском компьютере файлы программы клиента. Кроме того, скопируйте на клиент файлы Setup.bat, Cleanup.bat и ImportServiceCert.bat.

  4. На сервере выполните команду setup.bat service. При запуске команды setup.bat с аргументом service создается сертификат службы с полным именем домена компьютера и экспортируется в файл с именем Service.cer.

  5. Внесите в файл Service.exe.config службы изменения в соответствии с новым именем сертификата (в атрибуте findValue элемента serviceCertificate element of serviceCredentials), которое совпадает с полным именем домена компьютера.

  6. Скопируйте файл Service.cer из каталога службы в клиентский каталог на клиентском компьютере.

  7. На клиенте выполните команду setup.bat client. При выполнении команды setup.bat с аргументом client создается сертификат клиента с именем client.com, который экспортируется в файл с именем Client.cer.

  8. В файле Client.exe.config на клиентском компьютере измените значение адреса конечной точки, чтобы оно соответствовало новому адресу службы. Для этого замените имя localhost полным доменным именем сервера. Кроме того, необходимо изменить имя сертификата службы, чтобы оно совпадало с полным именем домена компьютера службы (в атрибуте findValue элемента defaultCertificate элемента serviceCertificate элемента clientCredentials).

  9. Скопируйте файл Client.cer из клиентского каталога в каталог службы на сервере.

  10. На клиенте запустите файл ImportServiceCert.bat. Он импортирует сертификат службы из файла Service.cer в хранилище CurrentUser - TrustedPeople.

  11. На сервере запустите файл ImportClientCert.bat. Он импортирует сертификат клиента из файла Client.cer в хранилище LocalMachine - TrustedPeople.

  12. На компьютере службы запустите из командной строки программу Service.exe.

  13. На клиентском компьютере из командной строки запустите программу Client.exe. Если клиенту и службе не удается взаимодействовать, см. раздел Troubleshooting Tips.

Очистка после образца

  • После завершения работы образца запустите в папке образцов файл Cleanup.bat.

    Aa395200.note(ru-ru,VS.100).gifПримечание
    Этот скрипт не удаляет сертификаты службы на клиенте при запуске образца на нескольких компьютерах. Если образцы Windows Communication Foundation (WCF), в которых использовались сертификаты, запускались на нескольких компьютерах, обязательно удалите сертификаты службы, которые были установлены в хранилище «CurrentUser — TrustedPeople». Для этого воспользуйтесь следующей командой: certmgr -del -r CurrentUser -s TrustedPeople -c -n <Fully Qualified Server Machine Name>. Пример: certmgr -del -r CurrentUser -s TrustedPeople -c -n server1.contoso.com.

Требования

Для этого образца необходимо установить и запустить MSMQ.

Демонстрации

Клиент шифрует сообщение с использованием открытого ключа службы и подписывает сообщение с помощью своего сертификата. Служба, считывающая сообщение из очереди, проверяет подлинность сертификата клиента с использованием сертификата в своем хранилище доверенных лиц. Затем она расшифровывает сообщение и перенаправляет сообщение операции службы.

Поскольку сообщение Windows Communication Foundation (WCF) передается в теле сообщения MSMQ, тело остается зашифрованным в хранилище MSMQ. Это защищает сообщение от нежелательного раскрытия информации. Обратите внимание, что сама служба MSMQ не содержит сведений о том, зашифрованы ли передаваемые через нее сообщения.

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

Описание

Код образца клиента и службы совпадает с кодом образца Привязка MSMQ с поддержкой транзакций с одним отличием. Для контракта операции в виде заметки задается уровень защиты, который предполагает, что сообщение должно подписываться и шифроваться.

    // Define a service contract. 
    [ServiceContract(Namespace="http://Microsoft.ServiceModel.Samples")]
    public interface IOrderProcessor
    {
        [OperationContract(IsOneWay = true, ProtectionLevel=ProtectionLevel.EncryptAndSign)]
        void SubmitPurchaseOrder(PurchaseOrder po);
    }

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

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

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <system.serviceModel>

    <client>
      <!-- Define NetMsmqEndpoint -->
      <endpoint address="net.msmq://localhost/private/ServiceModelSamplesMessageSecurity" 
                binding="netMsmqBinding" 
                bindingConfiguration="messageSecurityBinding"
                contract="Microsoft.ServiceModel.Samples.IOrderProcessor"
                behaviorConfiguration="ClientCertificateBehavior" />
    </client>

    <bindings>
        <netMsmqBinding>
            <binding name="messageSecurityBinding">
                <security mode="Message">
                    <message clientCredentialType="Certificate"/>
                </security>
            </binding>
        </netMsmqBinding>
    </bindings>

    <behaviors>
      <endpointBehaviors>
        <behavior name="ClientCertificateBehavior">
          <!-- 
        The clientCredentials behavior allows one to define a certificate to present to a service.
        A certificate is used by a client to authenticate itself to the service and provide message integrity.
        This configuration references the "client.com" certificate installed during the setup instructions.
        -->
          <clientCredentials>
            <clientCertificate findValue="client.com" storeLocation="CurrentUser" storeName="My" x509FindType="FindBySubjectName" />
            <serviceCertificate>
                <defaultCertificate findValue="localhost" storeLocation="CurrentUser" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
              <!-- 
            Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate 
            is in the user's Trusted People store, then it is trusted without performing a
            validation of the certificate's issuer chain. This setting is used here for convenience so that the 
            sample can be run without having to have certificates issued by a certification authority (CA).
            This setting is less secure than the default, ChainTrust. The security implications of this 
            setting should be carefully considered before using PeerOrChainTrust in production code. 
            -->
              <authentication certificateValidationMode="PeerOrChainTrust" />
            </serviceCertificate>
          </clientCredentials>
        </behavior>
      </endpointBehaviors>
    </behaviors>

  </system.serviceModel>
</configuration>

Обратите внимание, что задан режим безопасности Message, а атрибут ClientCredentialType имеет значение Certificate.

Конфигурация службы включает поведение службы, которое задает учетные данные службы, которые используются при проверке подлинности службы на стороне клиента. Имя субъекта сертификата сервера задается в атрибуте findValue в serviceCredentials element.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>

  <appSettings>
    <!-- Use appSetting to configure MSMQ queue name. -->
    <add key="queueName" value=".\private$\ServiceModelSamplesMessageSecurity" />
  </appSettings>

  <system.serviceModel>
    <services>
      <service 
          name="Microsoft.ServiceModel.Samples.OrderProcessorService"
          behaviorConfiguration="PurchaseOrderServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="https://localhost:8000/ServiceModelSamples/service"/>
          </baseAddresses>
        </host>
        <!-- Define NetMsmqEndpoint -->
        <endpoint address="net.msmq://localhost/private/ServiceModelSamplesMessageSecurity"
                  binding="netMsmqBinding"
                  bindingConfiguration="messageSecurityBinding"
                  contract="Microsoft.ServiceModel.Samples.IOrderProcessor" />
        <!-- The mex endpoint is exposed at https://localhost:8000/ServiceModelSamples/service/mex. -->
        <endpoint address="mex"
                  binding="mexHttpBinding"
                  contract="IMetadataExchange" />
      </service>
    </services>

    <bindings>
        <netMsmqBinding>
            <binding name="messageSecurityBinding">
                <security mode="Message">
                    <message clientCredentialType="Certificate" />
                </security>
            </binding>
        </netMsmqBinding>
    </bindings>

    <behaviors>
      <serviceBehaviors>
        <behavior name="PurchaseOrderServiceBehavior">
          <serviceMetadata httpGetEnabled="True"/>
          <!-- 
               The serviceCredentials behavior allows one to define a service certificate.
               A service certificate is used by the service to authenticate itself to its clients and to provide message protection.
               This configuration references the "localhost" certificate installed during the setup instructions.
          -->
          <serviceCredentials>
            <serviceCertificate findValue="localhost" storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
            <clientCertificate>
                <certificate findValue="client.com" storeLocation="LocalMachine" storeName="TrustedPeople" x509FindType="FindBySubjectName"/>
              <!-- 
            Setting the certificateValidationMode to PeerOrChainTrust means that if the certificate 
            is in the user's Trusted People store, then it is trusted without performing a
            validation of the certificate's issuer chain. This setting is used here for convenience so that the 
            sample can be run without having to have certificates issued by a certification authority (CA).
            This setting is less secure than the default, ChainTrust. The security implications of this 
            setting should be carefully considered before using PeerOrChainTrust in production code. 
            -->
              <authentication certificateValidationMode="PeerOrChainTrust" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>

  </system.serviceModel>

</configuration>

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

    // Service class which implements the service contract.
    // Added code to write output to the console window.
    public class OrderProcessorService : IOrderProcessor
    {
        private string GetCallerIdentity()
        {
            // The client certificate is not mapped to a Windows identity by default.
            // ServiceSecurityContext.PrimaryIdentity is populated based on the information
            // in the certificate that the client used to authenticate itself to the service.
            return ServiceSecurityContext.Current.PrimaryIdentity.Name;
        }

        [OperationBehavior(TransactionScopeRequired = true, TransactionAutoComplete = true)]
        public void SubmitPurchaseOrder(PurchaseOrder po)
        {
            Console.WriteLine("Client's Identity {0} ", GetCallerIdentity());
            Orders.Add(po);
            Console.WriteLine("Processing {0} ", po);
        }
  //…
}

При выполнении код службы выводит удостоверение клиента. Ниже показан образец результатов выполнения кода службы.

The service is ready.
Press <ENTER> to terminate service.

Client's Identity CN=client.com; ECA6629A3C695D01832D77EEE836E04891DE9D3C
Processing Purchase Order: 6536e097-da96-4773-9da3-77bab4345b5d
        Customer: somecustomer.com
        OrderDetails
                Order LineItem: 54 of Blue Widget @unit price: $29.99
                Order LineItem: 890 of Red Widget @unit price: $45.89
        Total cost of this order: $42461.56
        Order status: Pending

Комментарии

  • Создание сертификата клиента.

    Следующая строка пакетного файла создает сертификат клиента. В качестве имени субъекта создаваемого сертификата используется указанное имя клиента. Сертификат сохраняется в хранилище My в расположении CurrentUser.

    echo ************
    echo making client cert
    echo ************
    makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%CLIENT_NAME% -sky exchange -pe
    
  • Установка сертификата клиента в хранилище доверенных сертификатов сервера.

    Следующая строка пакетного файла копирует сертификат клиента в хранилище TrustedPeople сервера, чтобы сервер мог принимать соответствующие решения о доверии или недоверии. Чтобы установленный в хранилище TrustedPeople сертификат был доверенным для службы Windows Communication Foundation (WCF), для режима проверки сертификата клиента должно быть задано значение PeerOrChainTrust или PeerTrust. Чтобы узнать, как это сделать с помощью файла конфигурации, см. приведенный выше образец конфигурации службы.

    echo ************
    echo copying client cert to server's LocalMachine store
    echo ************
    certmgr.exe -add -r CurrentUser -s My -c -n %CLIENT_NAME% -r LocalMachine -s TrustedPeople 
    
  • Создание сертификата сервера.

    Следующие строки из файла Setup.bat создают используемый в дальнейшем сертификат сервера.

    echo ************
    echo Server cert setup starting
    echo %SERVER_NAME%
    echo ************
    echo making server cert
    echo ************
    makecert.exe -sr LocalMachine -ss MY -a sha1 -n CN=%SERVER_NAME% -sky exchange -pe
    

    Переменная %SERVER_NAME% задает имя сервера. Сертификат хранится в хранилище LocalMachine. Если пакетный файл запускается с аргументом «service» (например, setup.bat service), то переменная %SERVER_NAME% содержит полное доменное имя компьютера. В противном случае по умолчанию используется значение localhost.

  • Установка сертификата сервера в хранилище доверенных сертификатов клиента.

    Следующая строка копирует сертификат сервера в хранилище доверенных лиц клиента. Этот шаг является обязательным, поскольку сертификаты, созданные с помощью программы Makecert.exe, не получают неявного доверия со стороны клиентской системы. Если уже имеется сертификат, имеющий доверенный корневой сертификат клиента, например сертификат, выпущенный корпорацией Майкрософт, выполнять этот шаг по добавлению сертификата сервера в хранилище сертификатов клиента не требуется.

    certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
    
    Aa395200.note(ru-ru,VS.100).gifПримечание
    Если используется в англоязычном (не американском) выпуске Microsoft Windows, необходимо изменить файл Setup.bat и заменить имя учетной записи NT AUTHORITY\NETWORK SERVICE на эквивалент для соответствующего языка.

Aa395200.Important(ru-ru,VS.100).gif Примечание
Образцы уже могут быть установлены на компьютере. Перед продолжением проверьте следующий каталог (по умолчанию).

<диск_установки>:\WF_WCF_Samples

Если этот каталог не существует, перейдите на страницу Образцы Windows Communication Foundation (WCF) и Windows Workflow Foundation (WF) для .NET Framework 4, чтобы загрузить все образцы Windows Communication Foundation (WCF) и WF. Этот образец расположен в следующем каталоге.

<диск_установки>:\WF_WCF_Samples\WCF\Basic\Binding\Net\MSMQ\MessageSecurity