Аутентификация сертификата WCF не работает
Я построил клиент и сервер helloworld WCF. Я хочу использовать сертификат аутентификации между ними.
Я получаю сообщение об ошибке "Служба не прошла проверку подлинности".
Я создал два сертификата, используя makecert.exe. Сертификат на клиенте устанавливается в "Личные" и "Доверенные люди" и "Сторонние корневые центры сертификации". Я скопировал сертификат, так как не знаю, должен ли он быть только под одним заголовком
Мой сервер webconfig, как показано ниже
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
</appSettings>
<system.web>
<compilation debug="false" targetFramework="4.5.1"/>
<httpRuntime targetFramework="4.5.1"/>
</system.web>
<system.serviceModel>
<services>
<service behaviorConfiguration="BusinessToBusiness" name="TestHelloWork.Service1">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="BindingConfig" contract="TestHelloWork.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://win-gat-web01:7777/Service1"/>
</baseAddresses>
</host>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="BindingConfig">
<security>
<message clientCredentialType = "Certificate"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<behavior name="BusinessToBusiness">
<serviceCredentials>
<clientCertificate>
<authentication certificateValidationMode = "PeerTrust"/>
</clientCertificate>
<serviceCertificate findValue="WCfServer"
storeLocation="LocalMachine"
storeName="My"
x509FindType="FindBySubjectName" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
</system.serviceModel>
</configuration>
Клиентская сторона web.config, как показано ниже
<?xml version="1.0"?>
<!--
For more information on how to configure your ASP.NET application, please visit
http://go.microsoft.com/fwlink/?LinkId=169433
-->
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.5.1" />
<httpRuntime targetFramework="4.5.1" />
</system.web>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security>
<message clientCredentialType="Certificate" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://myserver:7777/Service.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
name="WSHttpBinding_IService1" behaviorConfiguration="CustomBehavior">
<identity>
<dns value="WCfServer" />
</identity>
</endpoint>
</client>
<behaviors>
<endpointBehaviors>
<behavior name="CustomBehavior">
<clientCredentials>
<clientCertificate findValue="WcfClient" x509FindType="FindBySubjectName"
storeLocation="CurrentUser" storeName="My" />
<serviceCertificate>
<authentication certificateValidationMode="PeerTrust"/>
</serviceCertificate>
</clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Сертификат на стороне клиента устанавливается в "Личный"
Есть идеи, что может быть не так? Я погуглил и понял, что они должны быть в одном домене? Но они. Также, как будет работать домен, если мой сервис внешний?
2 ответа
Попробуйте включить журнал CAPI2. Это специальный журнал (по умолчанию не включен), который содержит информацию о проверке сертификата. Если ваша проблема заключается в сбое процедуры проверки сертификата, вы найдете там полезную информацию. Ищите ошибки. В моем случае это было что-то вроде
- Цепочка сертификатов обработана, но завершена корневым сертификатом, который не является доверенным поставщиком доверия.
- Не удалось создать цепочку сертификатов для доверенного корневого центра.
- Функция отзыва не смогла проверить отзыв...
В моем случае у меня было
- Client.pfx импортируется в CurrentUser\My (персональное) хранилище на клиенте.
- Сертификат CA (ClientCA), выдавший файл client.pfx, был импортирован в доверенные корневые органы как в хранилище LocalMachine на клиенте, так и в хранилище LocalMachine на сервере.
- server.pfx импортируется в LocalMachine\ Мое (личное) хранилище на сервере
- Сертификат CA (ServerCA), выдавший файл server.pfx, импортированный в доверенные корневые органы как в хранилище LocalMachine на клиенте, так и в хранилище LocalMachine на сервере.
- CRL к клиенту CA доступен как с клиента, так и с сервера
- CRL на сервер CA доступен как от клиента, так и от сервера
Но вы используете PeerTrust
режим проверки сертификата, поэтому в соответствии с этим комментарием из демонстраций WCF у меня есть
Если для параметра certificateValidationMode задано значение PeerOrChainTrust, это означает, что если сертификат находится в хранилище доверенных лиц пользователя, ему будет доверено без проверки цепочки издателя сертификата. Этот параметр используется здесь для удобства, так что образец может быть запущен без необходимости иметь сертификаты, выданные центром сертификации (CA).
Я бы предположил, что сертификаты должны быть размещены так:
- client.cer (только сертификат из client.pfx) импортируется в хранилище доверенных лиц в хранилище LocalMachine на сервере
- server.cer (только сертификат из client.pfx), импортированный в хранилище доверенных лиц в хранилище CurrentUser на клиенте
Убедитесь, что вы предоставили права на закрытый ключ сервера для AppPool, под которым работает ваша служба IIS WCF (пул по умолчанию IIS APPPOOL\DefaultAppPool
) Это можно сделать используя mmc
или же certlm.msc
по праву кликая на сертификат сервера то All Tasks
-> Manage Private Keys ...
, Убедитесь, что вы НЕ выбрали AD, потому что IIS APPPOOL является локальной группой. Добавить аккаунт IIS APPPOOL\your_pool_name
и ударил ОК.
Это будет работать, если у вас есть настройки по умолчанию в вашем AppPool, как Identity
установлен в AplicationPoolIdentity
а не настраиваемая учетная запись (обычно используется управляемая учетная запись службы из AD) и Load User Profile
установлен в true
,
Проблема аутентификации сертификата WCF, с которой вы сталкиваетесь, скорее всего, связана с параметрами, используемыми при создании ваших самозаверяющих сертификатов с помощью MakeCert.
В частности, убедитесь, что ваш сертификат поддерживает необходимые параметры / цели. (Например, поле "Назначенные цели" сертификата должно содержать соответствующее значение, например "Аутентификация сервера" или "Аутентификация клиента".)
Следующая ссылка от Microsoft подробно описывает процесс.
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-temporary-certificates-for-use-during-development
Примечание: нашей команде повезло, используя инструмент SelfCert для быстрой разработки самозаверяющих сертификатов разработки.