Проверяющий элемент управления для сертификатов X.509
В этом образце показано, как реализовать пользовательский проверяющий элемент управления для сертификатов X.509. Это бывает полезным в случаях, когда ни один из встроенных режимов проверки сертификатов X.509 не соответствует требованиям приложения. В этом образце показана служба, содержащая пользовательский проверяющий элемент управления, который принимает самостоятельно выданные сертификаты. Клиент использует такие сертификаты для проверки подлинности службы.
Примечание. Поскольку выдаваемый самостоятельно сертификат может создаваться кем угодно, используемый службой пользовательский проверяющий элемент управления менее безопасен по сравнению с поведением по умолчанию, которое предоставляется режимом ChainTrust X509CertificateValidationMode. Перед использованием логики проверки в рабочей среде следует внимательно изучить связанные с этим проблемы безопасности.
Таким образом, в данном образце демонстрируются указанные ниже возможности.
Подлинность клиента может проверяться с помощью сертификата X.509.
Сервер проверяет учетные данные клиента с помощью пользовательского элемента X509CertificateValidator.
Сервер проходит проверку подлинности с использованием сертификата X.509 сервера.
Служба предоставляет доступ к одной конечной точке для взаимодействия со службой, определенной в файле конфигурации App.config. Конечная точка состоит из адреса, привязки и контракта. Привязка настраивается с помощью стандартного элемента wsHttpBinding, который по умолчанию использует для проверки подлинности сертификатов клиента WSSecurity . В поведении службы задается пользовательский режим проверки сертификатов X.509 клиентов, а также тип класса проверяющего элемента управления. Коме того, поведение с помощью элемента serviceCertificate задает сертификат сервера. Свойство SubjectName сертификата сервера должно совпадать со значением findValue в элементе конфигурации serviceCertificate element of serviceCredentials.
<system.serviceModel>
<services>
<service name="Microsoft.ServiceModel.Samples.CalculatorService"
behaviorConfiguration="CalculatorServiceBehavior">
<!-- use host/baseAddresses to configure base address -->
<!-- provided by host -->
<host>
<baseAddresses>
<add baseAddress =
"https://localhost:8001/servicemodelsamples/service" />
</baseAddresses>
</host>
<!-- use base address specified above, provide one endpoint -->
<endpoint address="certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding"
contract="Microsoft.ServiceModel.Samples.ICalculator" />
</service>
</services>
<bindings>
<wsHttpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
<serviceDebug includeExceptionDetailInFaults ="true"/>
<serviceCredentials>
<!--The serviceCredentials behavior allows one -->
<!-- to specify authentication constraints on -->
<!-- client certificates. -->
<clientCertificate>
<!-- Setting the certificateValidationMode to -->
<!-- Custom means that if the custom -->
<!-- X509CertificateValidator does NOT throw -->
<!-- an exception, then the provided certificate -- >
<!-- will be trusted without performing any -->
<!-- validation beyond that performed by the custom-->
<!-- validator. The security implications of this -->
<!-- setting should be carefully considered before -->
<!-- using Custom in production code. -->
<authentication
certificateValidationMode="Custom"
customCertificateValidatorType =
"Microsoft.ServiceModel.Samples.CustomX509CertificateValidator, service" />
</clientCertificate>
<!-- The serviceCredentials behavior allows one to -- >
<!--define a service certificate. -->
<!--A service certificate is used by a client to -->
<!--authenticate the service and provide message -->
<!--protection. This configuration references the -->
<!--"localhost" certificate installed during the setup -->
<!--instructions. -->
<serviceCertificate findValue="localhost"
storeLocation="LocalMachine"
storeName="My" x509FindType="FindBySubjectName" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Конфигурация конечной точки клиента состоит из имени конфигурации, абсолютного адреса конечной точки службы, привязки и контракта. Привязка клиента настраивается с помощью соответствующего режима и clientCredentialType сообщения.
<system.serviceModel>
<client>
<!-- X509 certificate based endpoint -->
<endpoint name="Certificate"
address=
"https://localhost:8001/servicemodelsamples/service/certificate"
binding="wsHttpBinding"
bindingConfiguration="Binding"
behaviorConfiguration="ClientCertificateBehavior"
contract="Microsoft.ServiceModel.Samples.ICalculator">
</endpoint>
</client>
<bindings>
<wsHttpBinding>
<!-- X509 certificate binding -->
<binding name="Binding">
<security mode="Message">
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="ClientCertificateBehavior">
<clientCredentials>
<serviceCertificate>
<!-- 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>
Реализация клиента задает используемый сертификат клиента.
// Create a client with Certificate endpoint configuration
CalculatorClient client = new CalculatorClient("Certificate");
try
{
client.ClientCredentials.ClientCertificate.SetCertificate(StoreLocation.CurrentUser, StoreName.My, X509FindType.FindBySubjectName, "test1");
// Call the Add service operation.
double value1 = 100.00D;
double value2 = 15.99D;
double result = client.Add(value1, value2);
Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);
// Call the Subtract service operation.
value1 = 145.00D;
value2 = 76.54D;
result = client.Subtract(value1, value2);
Console.WriteLine("Subtract({0},{1}) = {2}", value1, value2, result);
// Call the Multiply service operation.
value1 = 9.00D;
value2 = 81.25D;
result = client.Multiply(value1, value2);
Console.WriteLine("Multiply({0},{1}) = {2}", value1, value2, result);
// Call the Divide service operation.
value1 = 22.00D;
value2 = 7.00D;
result = client.Divide(value1, value2);
Console.WriteLine("Divide({0},{1}) = {2}", value1, value2, result);
client.Close();
}
catch (TimeoutException e)
{
Console.WriteLine("Call timed out : {0}", e.Message);
client.Abort();
}
catch (CommunicationException e)
{
Console.WriteLine("Call failed : {0}", e.Message);
client.Abort();
}
catch (Exception e)
{
Console.WriteLine("Call failed : {0}", e.Message);
client.Abort();
}
В этом образце для проверки сертификатов используется пользовательский элемент X509CertificateValidator. В образце реализуется элемент CustomX509CertificateValidator, унаследованный от X509CertificateValidator. Дополнительные сведения см. в документации по X509CertificateValidator. В данном образце пользовательского элемента управления реализуется метод Validate, принимающий все выданные самостоятельно сертификаты X.509, как показано в следующем фрагменте кода.
public class CustomX509CertificateValidator : X509CertificateValidator
{
public override void Validate ( X509Certificate2 certificate )
{
// Only accept self-issued certificates
if (certificate.Subject != certificate.Issuer)
throw new Exception("Certificate is not self-issued");
}
}
После реализации в коде службы проверяющего элемента управления необходимо проинформировать узел службы о проверяющем элементе управления, который следует использовать. Для этого можно воспользоваться следующим фрагментом кода.
serviceHost.Credentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.Custom;
serviceHost.Credentials.ClientCertificate.Authentication.CustomCertificateValidator = new CustomX509CertificateValidator();
Либо можно решить эту же задачу с помощью файла конфигурации, как показано ниже.
<behaviors>
<serviceBehaviors>
<behavior name="CalculatorServiceBehavior">
...
<serviceCredentials>
<!--The serviceCredentials behavior allows one to specify -->
<!--authentication constraints on client certificates.-->
<clientCertificate>
<!-- Setting the certificateValidationMode to Custom means -->
<!--that if the custom X509CertificateValidator does NOT -->
<!--throw an exception, then the provided certificate will-- >
<!-- be trusted without performing any validation beyond that-- >
<!-- performed by the custom validator. The security -- >
<!--implications of this setting should be carefully -- >
<!--considered before using Custom in production code. -->
<authentication certificateValidationMode="Custom"
customCertificateValidatorType =
"Microsoft.ServiceModel.Samples. CustomX509CertificateValidator, service" />
</clientCertificate>
...
</behavior>
</serviceBehaviors>
</behaviors>
При выполнении образца запросы и ответы операций отображаются в окне консоли клиента. Клиент должен успешно вызывать все методы. Чтобы закрыть клиент, нажмите клавишу ВВОД в окне клиента.
Пакетный файл Setup
Входящий в состав образца файл Setup.bat позволяет настроить для сервера соответствующие сертификаты, необходимые для выполнения резидентного приложения, которое требует обеспечения безопасности на основе сертификата сервера. Этот пакетный файл необходимо изменить, чтобы его можно было использовать на нескольких компьютерах или без размещения приложения.
Ниже представлен краткие общие сведения о различных разделах пакетных файлов, позволяющий изменять их для выполнения в соответствующей конфигурации.
Создание сертификата сервера.
Следующие строки из файла Setup.bat создают используемый в дальнейшем сертификат сервера. Переменная %SERVER_NAME% задает имя сервера. Измените эту переменную, чтобы задать собственное имя сервера. Значением по умолчанию является localhost.
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
Установка сертификата сервера в хранилище доверенных сертификатов клиента.
Следующие строки из файла Setup.bat копируют сертификат сервера в хранилище доверенных лиц клиента. Этот шаг является обязательным, поскольку сертификаты, созданные с помощью программы Makecert.exe, не получают неявного доверия со стороны клиентской системы. Если уже имеется сертификат, имеющий доверенный корневой сертификат клиента, например сертификат, выпущенный корпорацией Майкрософт, выполнять этот шаг по добавлению сертификата сервера в хранилище сертификатов клиента не требуется.
certmgr.exe -add -r LocalMachine -s My -c -n %SERVER_NAME% -r CurrentUser -s TrustedPeople
Создание сертификата клиента.
Следующие строки из файла Setup.bat создают сертификат клиента, который будет использоваться. Переменная %USER_NAME% задает имя клиента. Эта переменная имеет значение "test1", поскольку код клиента ищет именно это имя. Если изменить значение переменной %USER_NAME%, необходимо изменить и соответствующее значение в файле Client.cs и повторить построение клиента.
Сертификат хранится в хранилище "My store" (Личном хранилище) в расположении CurrentUser.
echo ************ echo Client cert setup starting echo %USER_NAME% echo ************ echo making client cert echo ************ makecert.exe -sr CurrentUser -ss MY -a sha1 -n CN=%USER_NAME% -sky exchange -pe
Установка сертификата клиента в хранилище доверенных сертификатов сервера.
Следующие строки из файла Setup.bat копируют сертификат клиента в хранилище доверенных лиц. Этот шаг является обязательным, поскольку сертификаты, созданные с помощью программы Makecert.exe, не получают неявного доверия со стороны серверной системы. Если уже имеется сертификат, имеющий доверенный корневой сертификат клиента, например сертификат, выпущенный корпорацией Майкрософт, выполнять этот шаг по добавлению сертификата клиента в хранилище сертификатов сервера не требуется.
certmgr.exe -add -r CurrentUser -s My -c -n %USER_NAME% -r LocalMachine -s TrustedPeople
Настройка и построение образца
Чтобы построить решение, следуйте инструкциям в разделе Построение образцов Windows Communication Foundation.
Чтобы запустить образец на одном или нескольких компьютерах, следуйте приведенным далее инструкциям.
Запуск образца на одном компьютере
Откройте окно командной строки Visual Studio 2010 с правами администратора и запустите файл Setup.bat из папки установки образца. При этом устанавливаются все сертификаты, необходимые для запуска образца.
Примечание o безопасности. Пакетный файл Setup.bat предназначен для запуска из командной строки Visual Studio 2010. Переменная среды PATH, заданная в командной строке Visual Studio 2010, указывает на каталог, содержащий исполняемые файлы, необходимые для скрипта Setup.bat. Запустите программу Service.exe из папки service\bin.
Запустите программу Client.exe из каталога \client\bin. Действия клиента отображаются в консольном приложении клиента.
Если клиенту и службе не удается взаимодействовать, см. раздел Troubleshooting Tips.
Запуск образца на нескольких компьютерах
Создайте каталог на компьютере службы.
Скопируйте файлы служебной программы из каталога \service\bin в виртуальный каталог на компьютере службы. Кроме того, скопируйте на компьютер службы файлы Setup.bat, Cleanup.bat, GetComputerName.vbs и ImportClientCert.bat.
Создайте на клиентском компьютере каталог для двоичных файлов клиента.
Скопируйте в клиентский каталог на клиентском компьютере файлы программы клиента. Кроме того, скопируйте на клиент файлы Setup.bat, Cleanup.bat и ImportServiceCert.bat.
На сервере откройте командную строку Visual Studio с правами администратора и запустите
setup.bat service
. При запуске командыsetup.bat
с аргументомservice
создается сертификат службы с полным именем домена компьютера, который экспортируется в файл с именем Service.cer.Внесите в файл Service.exe.config изменения в соответствии с новым именем сертификата (в атрибуте findValue в serviceCertificate element of serviceCredentials), которое совпадает с полным именем домена компьютера. Кроме того, измените имя компьютера в элементе <service>/<baseAddresses> с localhost на полное доменное имя компьютера службы.
Скопируйте файл Service.cer из каталога службы в клиентский каталог на клиентском компьютере.
На клиентском компьютере запустите
setup.bat client
из командной строки Visual Studio, открытой с правами администратора. При выполнении командыsetup.bat
с аргументомclient
создается сертификат клиента с именем client.com, который экспортируется в файл с именем Client.cer.В файле Client.exe.config на клиентском компьютере измените значение адреса конечной точки, чтобы оно соответствовало новому адресу службы. Для этого замените имя localhost полным доменным именем сервера.
Скопируйте файл Client.cer из клиентского каталога в каталог службы на сервере.
На клиентском компьютере откройте командную строку Visual Studio с правами администратора и запустите файл ImportServiceCert.bat. Он импортирует сертификат службы из файла Service.cer в хранилище CurrentUser - TrustedPeople.
На сервере откройте командную строку Visual Studio с правами администратора и запустите файл ImportClientCert.bat. При этом импортируется сертификат клиента из файла Client.cer в хранилище «LocalMachine — TrustedPeople».
На сервере запустите из окна командной строки программу Service.exe.
На клиентском компьютере из окна командной строки запустите программу Client.exe. Если клиенту и службе не удается взаимодействовать, см. раздел Troubleshooting Tips.
Очистка после образца
- После завершения работы образца запустите в папке образцов файл 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 .
|