2010-11-03 2 views
12

Я пытаюсь получить доступ к общедоступной веб-службе SOAP (а не к WCF) через https, и я получаю сообщение об ошибке, которого я никогда раньше не видел. Во-первых, вот факты:Как заставить клиента WCF отправить сертификат клиента?

  • Эта услуга требует сертификатов клиентов. У меня есть сертификат, подписанный тем же СА, что и сертификат сервера.
  • Я знаю, что URL доступен, так как я могу ударить его в Internet Explorer. IE открывает окно «выбрать сертификат», и если я его выберу (и проигнорирую ошибку сервера-хоста-имени-не-совпадения-сертификата), он продолжит и даст мне ошибку HTTP 500.
  • Если я открою сайт в Chrome, после выбора сертификата и игнорирования ошибки, я получаю нормальное сообщение об ошибке WSA Action = null.
  • Если я открываю сайт в FireFox, после игнорирования ошибки, я получаю страницу о том, как сервер не смог проверить мой сертификат. Он никогда не просил меня выбрать один, так что это имеет смысл.

Теперь исключение:

Error occurred while executing test 12302: System.ServiceModel.Security.SecurityNegotiationException: Could not establish secure channel for SSL/TLS with authority 'ihexds.nist.gov:9085'. ---> System.Net.WebException: The request was aborted: Could not create SSL/TLS secure channel. 
    at System.Net.HttpWebRequest.GetResponse() 
    at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout) 

Я проследил взаимодействие с WireShark, а потому, что я не эксперт в протоколе TLS, я мог не быть подсказки относительно того, что происходит , Здесь, однако, это то, что я вижу:

  1. C -> S Client Hello
    • Содержит такие вещи, как случайное число, дата/время, поддерживается Cypher люкс и т.д.
  2. S - > C сервера Здравствуйте, сертификат, сертификат запрос, сервер Здравствуйте Done
    • Содержит сертификат сервера, и запрос на сертификат клиента
  3. C -> S сертификат, клиент обмена ключами, изменение Cipher Spec, Encrypted Рукопожатие Сообщение
    • ВОТ ИНТЕРЕСНО ЧАСТЬ - Первая часть этого пакета квитирование сертификат, в котором я принимаю сертификат клиента но сертификаты отсутствуют (Длина сертификатов: 0).
  4. S -> C Предупреждение (Уровень: Fatal, Описание: Bad Certificate)
    • Ну да, там не было никакого сертификата отправлено.

Мои связывания устанавливается следующим образом:

<binding name="https_binding"> 
    <textMessageEncoding /> 
    <httpsTransport useDefaultWebProxy="false" /> 
</binding> 

Мое поведение устанавливается следующим образом:

<behavior name="clientcred"> 
    <clientCredentials> 
     <clientCertificate findValue="69b6fbbc615a20dc272a79caa201fe3f505664c3" storeLocation="CurrentUser" storeName="My" x509FindType="FindByThumbprint" /> 
     <serviceCertificate> 
      <authentication certificateValidationMode="None" revocationMode="NoCheck" /> 
     </serviceCertificate> 
    </clientCredentials> 
    <messageInspector /> 
</behavior> 

Моя конечная точка настроена использовать как связывание и поведение. Почему WCF отказывается отправлять сертификат при создании соединения https?

ответ

9

Я решил проблему, но я не понимаю, почему это изменение конфигурации исправило это. Я изменил эту строку:

<httpsTransport useDefaultWebProxy="false" /> 

к этому:

<httpsTransport useDefaultWebProxy="false" requireClientCertificate="true" /> 

и волшебно он начал работать. Я понял, что «кнопка» requireClientCertificate была для серверной, поэтому я не пробовал ее во время моих споров. Видимо, я был неправ.

+0

Я так ненавижу WCF. Это решение сработало для меня, благодаря кучам - но все это так неудобно. Убей меня сейчас. – robnick

-1

Это может быть проблема, связанная с использованием протокола безопасности.В частности, они думают, что серверу может не понравиться WCF, пытающийся использовать TLS 1.0.

Чтобы увидеть, если это так, попробуйте добавить следующее перед вызовом службы

System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3 

Это может быть добавлен либо в коде клиента или путем размещения его в IEndpointBehavior

+0

Я пробовал это, и это не изменило результаты. Я знаю, что сервер поддерживает TLS 1.0 (и только один конкретный шифр, на самом деле, но этот шифр находится в списке, отправленном на сервер в рукопожатии). – Mark

+0

Не, если обмен получил до сообщения ChangeCipherSpec. Это означает, что все о протоколе согласовано. – EJP

2

Там должно было быть CertificateRequest с сервера, именования допустимых типов сертификатов и центров сертификации. Если ваш сертификат не соответствует указанным, он не будет отправлен.

+0

Был запрос сертификата (см. № 2), и он действительно содержал список ЦС и типов сертификатов. У меня действительно есть соответствующий сертификат, и это тот, который указан в поведении. – Mark

+0

Если все это верно, было бы сообщение сертификата от клиента после CertificateRequest с сервера. Неизбежный вывод состоит в том, что некоторые из них неверны. Вам нужно дважды проверить все: в частности, что сертификат (а) доступен для приложения и (б) соответствует всем ограничениям, выраженным в CertificateRequest. – EJP

+0

Это достоверно верно ... У меня есть захват WireShark прямо здесь. Однако я решил решить эту проблему, но я не совсем понимаю, почему я изменил ее. Я отправлю его в отдельном ответе. – Mark

Смежные вопросы