Я занимаюсь разработкой веб-приложения ASP.NET, которое отправляет запрос на другой сервер с помощью HttpWebRequest.Он отправляет запрос по HTTPS, а удаленному серверу требуется сертификат клиента.Сбой запроса в приложении .NET, по-видимому, не удается отправить правильный сертификат клиента.Я могу успешно подключиться и отправить сертификат клиента, если я просто захожу на URL через веб-браузер (в частности, в Chrome).
Приведенный ниже код является простым воспроизведением, с простойGET request.
var r = WebRequest.Create(url) as HttpWebRequest;
r.ClientCertificates = new X509CertificateCollection { myX509Cert };
using (var resp = r.GetResponse() as HttpWebResponse) {
...
}
Я получил наше любимое исключение: «Не удалось создать безопасный канал SSL / TLS».Как правило, эти типы проблем указывают на проблемы с разрешениями на закрытый ключ вашего сертификата.Я перепробовал все, что мог, чтобы убедиться, что все настроено правильно, но, возможно, я что-то упустил.Короче говоря, удаленный сервер отправляет TLS CertificateRequest
со списком, который, похоже, правильно идентифицирует мой клиентский сертификат, но мое приложение не может ответить ни одним клиентским сертификатом.
Вот мои настройки:
- 64-битная Windows 7 профессиональная
- Возможность воспроизвести проблему в приложении ASP.NET MVC 3 / .NET 4, работающем на сервере разработки Visual Studio, ASP.NET WebForms /Приложение .NET 3.5, работающее как в локальном IIS, так и в консольном приложении .NET / .NET 4
- Microsoft .NET Framework 4.5 было недавно установлено.Еще не изучили, может ли это быть проблемой
Вот все, что я пробовал, и то, что я знаю:
- Этот код работал нормально при запускена компьютере с Windows XP
- я гарантировал, что мой клиентский сертификат импортирован в локальный компьютер, хранилище личных сертификатов, с разрешениями личного ключа, правильно настроенными для меня и всех соответствующих пользователей IIS
- Я попыталсяпереустановка сертификата на моей машине пару раз
- Я подтвердил, что приложение .NET может получить доступ к сертификату X509 и
HasPrivateKey
= true - Гарантировал, что мой сертификат клиента действителен.На самом деле это сертификат SSL для веб-сервера, на котором будет работать это приложение
- Я установил
PreAuthenticate = true
в объекте запроса.Не сделал различий - Я попытался установить
ServicePointManager.Expect100Continue = false
, не сделал различий - Я попытался установить
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3
, но, очевидно, удаленный сервер требует TLS, такэто не помогает - Я установил
ServicePointManager.ServerCertificateValidationCallback
делегат, чтобы всегда возвращать true.Но запрос не выполняется ранее при подтверждении связи TLS, прежде чем он даже доходит до точки вызова этого делегата - Когда я перехожу по URL-адресу в Chrome, он запрашивает у меня сертификат клиента, представляет правильный сертификат клиентав качестве выбора я выбираю этот сертификат и получаю действительный ответ.Также работает правильно, когда я создаю запрос в Fiddler.Поэтому определенно возникает проблема с моим кодом .NET, а не с самим сертификатом или с удаленным сервером и т. Д.
- Поставщик, с которым я работаю, настроил ту же службу на другом удаленном сервере.и эта служба требует другого сертификата клиента.Поэтому я попытался сделать то же самое с другим URL-адресом и сертификатом клиента и получил тот же сбой
Я добавил System.Net trace и увидел это:
SecureChannel # 26717201 - У нас есть предоставленные пользователем сертификаты.Сервер указал 6 эмитентов.Ищите сертификаты, которые соответствуют любому из эмитентов.
SecureChannel # 26717201 - осталось с 0 клиентскими сертификатами на выбор.
...
InitializeSecurityContext (количество в буферах= 2, длина Out-Buffer = 0, возвращенный код = CertUnknown).
Я включил полное протоколирование SCHANNEL и увидел это предупреждение:
Удаленный сервер запросил аутентификацию клиента SSL, но не удалось найти подходящий сертификат клиента. Будет предпринята попытка анонимного подключения. Этот запрос на соединение SSL может быть успешным или неуспешным, в зависимости от настроек политики сервера.
Я запустил Wireshark и увидел, что удаленный сервер отправил CertificateRequest
, и, похоже, запись Distinguished Name
имеет значения CN \ OU \ O моего клиентского сертификата, указанные точно. После этого мое приложение отправляет ответ сертификата без сертификатов.
Кажется, что я что-то упускаю при настройке этого сертификата для правильной работы с приложениями .NET в Windows 7. Я думаю, что на моем новом компьютере с Windows 7 что-то другое, по сравнению с компьютером с XP, то есть заставляя это потерпеть неудачу сейчас. У меня нет доступа к среде Windows XP, чтобы подтвердить это; Я через пару дней, но очень хотел бы разрешить это как можно скорее.
Любые идеи будут высоко оценены. Спасибо!
EDIT Как описано выше, при подключении к URL-адресу в Chrome браузер запрашивает у меня сертификат клиента, и я могу предоставить правильный сертификат и успешно подключиться. Однако я не могу сделать это успешно в Internet Explorer (9). Я просто получаю «Internet Explorer не может отобразить веб-страницу», без каких-либо других подсказок или объяснений. Мне сказали, что это может быть актуально, поскольку WebRequest.Create
имеет поведение, подобное IE. Я изучаю, что это может означать, но оценил бы любые мысли по этому поводу.
EDIT Кроме того, я должен отметить, что удаленный сервер использует самозаверяющий сертификат SSL. Первоначально я думал, что это может быть проблемой, поэтому я добавил сертификат в качестве доверенного корня в MMC, чтобы сертификат был действительным на моем компьютере. Это не решило проблему.