Сертификат службы WCF и идентификация конечной точки на стороне клиента - почему это не работает? - PullRequest
10 голосов
/ 09 ноября 2009

[Обновить] - я прилагаю также полные конфигурационные файлы, для службы и для клиента (вне здесь, чтобы не затопить тему)

У меня ситуация почти такая же, как описанная в этом вопросе, однако мой вопрос несколько отличается.

  • Я использую NetTcpBinding с безопасностью установить значение TransportWithMessageCredential
  • Я использую пароль / имя пользователя учетные данные, заархивированные ASP.NET поставщик
  • Мой сервис размещен в Windows Сервис
  • У меня есть поведение в моей конечной точке указанная аутентификация revocationMode = "NOCHECK"

Требуется, чтобы служба предоставляла сертификат для аутентификации клиентов. Это нормально, я просто делаю:

<serviceCertificate findValue="***"
                    storeLocation="CurrentUser"
                    storeName="My"
                    x509FindType="FindByThumbprint"/>

Так вот, я немного подумал, что теперь у клиента будет

<identity>
  <certificate encodedValue="encoded certificate"/>
</identity>

И он сможет проверить учетные данные службы , не установив этот сертификат в хранилище на клиентском компьютере .

Я был удивлен , узнав , что, хотя я устанавливаю учетные данные службы для сертификата, WSDL выставляет

<Identity>
   <Dns>Foo</Dns>
</Identity>

Опять же, в сервисе я могу установить Identity для CertificateReference и подключить его к тому же сертификату, а затем WSDL представит идентификацию как X509Certificate, но когда я запускаю клиент, этот параметр игнорируется, и я получаю сообщение об ошибке:

System.ServiceModel.Security.SecurityNegotiationException: Сертификат X.509 CN = xxx не находится в магазин доверенных людей. X.509 сертификат CN = ххх строительство цепи не удалось. Сертификат, который был использован имеет цепочку доверия, которая не может быть проверено. Заменить сертификат или измените CertificateValidationMode. Цепочка сертификатов обработана, но завершается корневым сертификатом, который не является доверенным поставщиком доверия.

Есть ли способ заставить клиента использовать это значение из конфигурации и работать без необходимости устанавливать сервисный сертификат (или его корневой) на клиентской машине?

[UPDATE] Если для атрибута certificateValidationMode задано значение none, исключение исчезнет, ​​но это неприемлемое решение с точки зрения безопасности.

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

Ответы [ 5 ]

4 голосов
/ 10 ноября 2009

Эскиз решения:

1) Определить и зарегистрировать пользовательский X509CertificateValidator на клиенте

2) В методе Validate сравните данный сертификат с сертификатом, присутствующим в свойстве EndpointAddress.Identity клиента. Объект, на который ссылается это свойство, должен иметь точный тип X509CertificateEndpointIdentity .

Я не тестировал это решение, однако оно имеет для меня смысл.

НТН Pedro

2 голосов
/ 06 ноября 2012

Извините, я не могу комментировать другие ответы.

Я только что проверил это в .NET 4.0 и могу подтвердить, что ответ "Zeratul" правильный. Для проверки подлинности сервера достаточно явно указать идентификатор службы либо в конфигурации, либо программно. Нет необходимости проверять сертификат любыми другими способами (то есть вы можете установить для «certificateValidationMode» значение «Нет»), поскольку вы используете метод окончательной проверки - сравнение отпечатка сертификата.

@ AlexDrenea

«serviceCertificate» не используется для проверки. Он используется с защитой сообщений для шифрования сообщений перед их отправкой на сервер. См. Документацию Microsoft об этом:

http://msdn.microsoft.com/en-us/library/ms731782.aspx

2 голосов
/ 10 марта 2011

[ОБНОВЛЕНИЕ] Во время настройки certificateValidationMode to none будет сделать исключение уйти, это неприемлемое решение из безопасности точка зрения.

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

Вы не правы. Это будет отлично. Это на самом деле то, что вы хотите - ваш сертификат на не будет проверен. Все, что вам нужно, это установить идентификатор конечной точки на клиенте на

<identity>
  <certificate encodedValue="encoded certificate"/>
</identity>

Когда клиент подключается к серверу, WCF сравнивает два сертификата и выдает исключение, если они не совпадают. И вы в полной безопасности.

Использование настраиваемого валидатора, такого как Педро Феликс , совершенно не требуется в вашем случае. Это именно то, для чего предназначена конечная точка.

1 голос
/ 10 марта 2011

Это дополнительный комментарий к моему предыдущему ответу. Извините, я не могу комментировать ответы.

Более того, вам не необходимо установить любую личность на сервере. Забудьте о том, что WSDL говорит вам о личности сервера. Идентификатор удаленной конечной точки службы определяется клиентом во время выполнения. Если сервер использует SSL, то у него есть несколько идентификаторов: общее имя сертификата (то есть идентификатор DNS), идентификатор сертификата и идентификатор RSA (не уверен насчет последнего). Поэтому вы можете проверить идентичность сервера по любому из этих критериев (или по нескольким из них).

0 голосов
/ 09 ноября 2009

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

 <behaviors>
  <endpointBehaviors>
    <behavior name="SecureMessageUserName">
      <clientCredentials>
         <serviceCertificate>
            <authentication revocationMode="NoCheck"/>
         </serviceCertificate>
      </clientCredentials>
    </behavior>
  </endpointBehaviors>
 </behaviors>

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

Редактировать извините за задержку

Вы также должны добавить noCheck в конфигурацию сервера:

<behavior name="X509SecureBehavior">
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceCredentials>
            <serviceCertificate storeName="My" storeLocation="CurrentUser" x509FindType="FindByThumbprint" findValue="aaaa" />
            <clientCertificate>
              <authentication certificateValidationMode="None" revocationMode="NoCheck" />
            </clientCertificate>
          </serviceCredentials>
        </behavior>

Также я не включил ссылку на сертификат в определение конечной точки.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...