Сертификат службы WCF и идентификатор конечной точки клиентской стороны - почему он не работает?
[Обновление]. Я также добавляю полные конфигурационные файлы для service, а для клиент (вне этого, чтобы не заливать тему)
У меня ситуация довольно похожа на ситуацию, описанную в этом, однако мой вопрос несколько иной.
- Я использую NetTcpBinding с безопасностью
установить в TransportWithMessageCredential
- Я использую пароль/имя пользователя
учетные данные, поддерживаемые ASP.NET
провайдер
- Мой сервис находится в Windows
Сервис
- У меня do есть поведение моей конечной точки
заданная проверка
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 = xxx строительство цепочки не смогли. Сертификат, который был использован имеет цепочку доверия, которая не может быть проверено. Заменить сертификат или измените сертификатValidationMode. Обработана цепочка сертификатов, но завершено в корневом сертификате, который не доверяет поставщик доверия.
Есть ли способ заставить клиента использовать это значение из конфигурации и работы без необходимости установки сертификата службы (или его корня) на машине клиента?
[ОБНОВЛЕНИЕ]
Пока значение параметра certificateValidationMode не будет отменено, исключение будет исключено, это неприемлемое решение с точки зрения безопасности.
Это заставляет клиента просто признать, что он получает сертификат "some", не вдаваясь в подробности. Это делает возможным весь диапазон людей в средних атаках. Он по-прежнему не будет проверять информацию, отправленную (предполагаемой) службой, на сертификат, сбрасываемый в config.
Ответы
Ответ 1
Эскиз решения:
1) Определите и зарегистрируйте пользовательский X509CertificateValidator на клиенте
2) В методе Подтвердить сравните данный сертификат с тем, который присутствует в объекте EndpointAddress.Identity. Объект, на который ссылается это свойство, должен иметь точный тип X509CertificateEndpointIdentity.
Я не тестировал это решение, но это имеет для меня смысл.
НТН
Педро
Ответ 2
[ОБНОВЛЕНИЕ] При установке certificateValidationMode никому не будет исключить исключение, неприемлемое решение безопасности точки зрения.
Это заставляет клиента просто признать что он получает "некоторый" сертификат, не вдаваясь в подробности. Эта делает весь круг людей посередине возможны атаки. Он все равно не будет подтвердите информацию, отправленную (предполагаемой) службы против сертификат сбрасывается в config.
Вы ошибаетесь. Это будет отлично. Это на самом деле то, что вы хотите - ваш сертификат не должен быть проверен.
Все, что вам нужно, - установить личность конечной точки на клиенте на
<identity>
<certificate encodedValue="encoded certificate"/>
</identity>
Когда клиент подключается к серверу, WCF будет сравнивать два сертификата и выдавать исключение, если они не совпадают. И вы совершенно безопасны.
Использование специального валидатора, такого как Педро Феликс, предлагается в вашем случае совершенно ненужно. Именно это означает тождество конечной точки.
Ответ 3
Извините, я не могу комментировать другие ответы.
Я только что протестировал это в .NET 4.0, и я могу подтвердить, что ответ "Зератул" верен. Явно настраивает идентификатор службы либо в конфигурации, либо программно достаточно для аутентификации сервера. Нет необходимости проверять сертификат другими способами (т.е. Вы можете установить "certificateValidationMode" на "None" ), поскольку вы используете метод окончательной проверки - сравнение отпечатка сертификата.
@AlexDrenea
"serviceCertificate" не используется для проверки. Он используется с защитой сообщений для шифрования сообщений до их отправки на сервер. См. Документацию по этому вопросу в Microsoft:
http://msdn.microsoft.com/en-us/library/ms731782.aspx
Ответ 4
Это дополнительный комментарий к моему предыдущему ответу. Извините, я не могу комментировать ответы.
Кроме того, вам нужно не установить на сервере любую. Забудьте о том, что WSDL сообщает вам о личности сервера. Идентификация конечной точки удаленного сервиса определяется клиентом во время выполнения. Если сервер использует SSL, он имеет несколько идентификаторов: общее имя сертификата (то есть идентификатор DNS), идентификатор сертификата и идентификатор RSA (не уверен в последнем). Таким образом, вы можете проверить идентификатор сервера любым из этих критериев (или несколькими из них).
Ответ 5
Вы зависите и почти закончили настройку конфигурации клиента. Вам не хватает последней информации (как указано в описании ошибки): вам нужно установить для параметра 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>
Также я не включил ссылку сертификата в определение конечной точки.