Безопасность сообщений в среде очередей сообщений
В примере MessageSecurity показано, как реализовать приложение, использующее WS-Security с проверкой подлинности сертификата X.509v3 для клиента, и требует проверки подлинности сервера с помощью сертификата X.509v3 по протоколу MSMQ. Безопасность сообщений иногда является более желательной, чтобы сообщения в хранилище MSMQ оставались зашифрованными, и приложение может выполнять собственную проверку подлинности сообщения.
Этот пример основан на примере с транзакционной привязкой MSMQ. Сообщения шифруются и подписываются.
Настройка, сборка и запуск примера
Убедитесь, что вы выполнили процедуру установки One-Time для примеров Windows Communication Foundation.
Если сначала запущена служба, она проверит наличие очереди. Если очередь отсутствует, служба создаст ее. Сначала можно запустить службу для создания очереди или создать ее с помощью диспетчера очередей MSMQ. Выполните следующие действия, чтобы создать очередь в Windows 2008.
Откройте диспетчер серверов в Visual Studio 2012.
Разверните вкладку "Функции" .
Щелкните правой кнопкой мыши Очереди частных сообщенийи выберите Создать, Частную очередь.
Установите флажок транзакционная.
Введите
ServiceModelSamplesTransacted
в качестве имени новой очереди.
Чтобы создать версию решения на C# или Visual Basic, следуйте инструкциям в разделе постройки примеров Windows Communication Foundation.
Запуск примера на том же компьютере
Убедитесь, что путь содержит папку, содержащую Makecert.exe и FindPrivateKey.exe.
Запустите Setup.bat из папки установки примера. При этом устанавливаются все сертификаты, необходимые для выполнения примера.
Заметка
Убедитесь, что вы удалите сертификаты, выполнив Cleanup.bat после завершения работы с примером. Другие примеры безопасности используют те же сертификаты.
Запустите Service.exe из \service\bin.
Запустите Client.exe из \client\bin. Действие клиента отображается в клиентском консольном приложении.
Если клиент и служба не могут взаимодействовать, см. советы по устранению неполадок для примеров WCF.
Чтобы запустить программу-пример на нескольких компьютерах
Скопируйте Setup.bat, Cleanup.batи ImportClientCert.bat файлы на компьютер службы.
Создайте каталог на клиентском компьютере для двоичных файлов клиента.
Скопируйте файлы клиентской программы в каталог клиента на клиентском компьютере. Кроме того, скопируйте Setup.bat, Cleanup.batи ImportServiceCert.bat файлы в клиент.
На сервере запустите
setup.bat service
. При выполненииsetup.bat
с аргументомservice
создается сертификат службы с полным доменным именем компьютера и экспортируется сертификат службы в файл с именем Service.cer.Измените service.exe.config службы, чтобы отразить новое имя сертификата (в атрибуте
findValue
в <serviceCertificate>), которое совпадает с полным доменным именем компьютера.Скопируйте файл Service.cer из каталога службы в клиентский каталог на клиентском компьютере.
На клиенте запустите
setup.bat client
. При выполненииsetup.bat
с аргументомclient
создается сертификат клиента с именем client.com и экспортируется сертификат клиента в файл с именем Client.cer.В файле Client.exe.config на клиентском компьютере измените значение адреса конечной точки на соответствие новому адресу службы. Для этого замените localhost полным доменным именем сервера. Кроме того, необходимо изменить имя сертификата службы, чтобы оно соответствовало полному доменному имени компьютера службы (в атрибуте
findValue
элементаdefaultCertificate
вserviceCertificate
, находящемся вclientCredentials
).Скопируйте файл Client.cer из клиентского каталога в каталог службы на сервере.
На клиенте запустите
ImportServiceCert.bat
. При этом сертификат службы импортируется из файла Service.cer в хранилище CurrentUser — TrustedPeople.На сервере запустите
ImportClientCert.bat
. Это импортирует сертификат клиента из файла Client.cer в хранилище LocalMachine — TrustedPeople.На компьютере службы запустите Service.exe из командной строки.
На клиентском компьютере запустите Client.exe из командной строки. Если клиент и служба не могут взаимодействовать, обратитесь к разделу Рекомендации по устранению неполадок для примеров WCF.
Очистка после образца
Запустите Cleanup.bat в папке примеров после завершения работы примера.
Заметка
Этот скрипт не удаляет сертификаты службы на клиенте при запуске этого примера на компьютерах. Если вы запускали примеры из 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. Сертификаты обмениваются вне диапазона. Это всегда относится к приложению с очередью, так как служба и клиент не должны работать одновременно.
Описание
Пример кода клиента и сервиса такой же, как в примере привязки Transacted 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>.
<?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="http://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 http://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. Если пакетный файл установки выполняется с аргументом службы (например,
setup.bat service
), %SERVER_NAME% содержит полное доменное имя компьютера. В противном случае, по умолчанию используется localhost.Установка сертификата сервера в доверенное хранилище сертификатов клиента.
В следующей строке сертификат сервера копируется в хранилище доверенных пользователей клиента. Этот шаг необходим, так как сертификаты, созданные Makecert.exe, не являются неявно доверенными клиентской системой. Если у вас уже есть сертификат, который основывается на корневом сертификате, которому доверяет клиент, например, выданный корпорацией Microsoft, то этап добавления серверного сертификата в хранилище клиентских сертификатов не требуется.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Заметка
Если вы используете неамериканскую английскую версию Microsoft Windows, необходимо изменить файл Setup.bat и заменить имя учетной записи "NT AUTHORITY\NETWORK SERVICE" на ваш региональный эквивалент.