Внедрить клиент C#, который использует WebServices через SSL?
-
21-08-2019 - |
Вопрос
Итак, я добавил ServiceReference в консольное приложение C#, которое вызывает веб-службу, предоставляемую Oracle.
У меня все настроено, и все работает отлично, когда не используется SSL (http).Сейчас я пытаюсь настроить его с помощью SSL, и у меня возникают проблемы с добавлением его в ссылки на службы (или даже в веб-ссылки).Например, URL-адрес (https), по которому предоставляется служба, не возвращает соответствующие веб-методы, когда я пытаюсь добавить его в Visual Studio.
Базовое соединение было закрыто:При отправке произошла непредвиденная ошибка.Получен неожиданный EOF или 0 байт из транспортного потока.Метаданные содержат ссылку, которую невозможно разрешить:'https://srs204.mywebsite.ca:7776/SomeDirectory/MyWebService?WSDL'
Еще одна проблема, с которой я столкнулся, связана с управлением и развертыванием сертификатов.У меня есть около 1000 внешних клиентских сайтов, которым потребуется использовать эту небольшую утилиту, и им потребуется установить сертификат в соответствующем хранилище сертификатов, чтобы подключиться к веб-службе.Не уверен, что это лучший подход к решению этой проблемы.Должны ли они быть в корневом хранилище?
Я провел немало часов в Интернете, просматривая различные варианты, но нигде не смог получить четкого ответа.
Подводя итог, у меня есть пара вопросов:
1) У кого-нибудь есть хорошие ссылки по настройке веб-служб в Visual Studio, использующих SSL?
2) Как мне зарегистрировать сертификат?В каком магазине он должен быть?Могу ли я просто использовать что-то вроде CertMgr для его регистрации?
Должна быть хорошая книга/учебник/что-то еще, что покажет мне общие передовые методы настройки чего-то подобного.Я просто не могу его найти!
Решение
Ну, я это понял.Это заняло у меня гораздо больше времени, чем мне хотелось бы говорить, но я хотел поделиться своим решением, поскольку для меня ОГРОМНАЯ любимая мозоль - видеть стандарт.«О, я исправил это!Спасибо!" посты, которые заставляют всех задуматься о том, что же произошло на самом деле.
Так.
Основная проблема заключалась в том, что по умолчанию Visual Studio 2008 использует TLS для подтверждения SSL, а веб-служба на базе Oracle/Java, к которой я пытался подключиться, использовала SSL3.
Когда вы используете «Добавить ссылку на службу...» в Visual Studio 2008, у вас есть нет возможности указать, что протокол безопасности для менеджера точек обслуживания должен быть SSL3.
Пока не.
Вы берете статический документ WSDL и используйте wsdl.exe для создания прокси-класса.
wsdl /l:CS /protocol:SOAP /namespace:MyNamespace MyWebService.wsdl
Затем вы можете использовать Компилятор C Sharp чтобы превратить этот прокси-класс в библиотеку (.dll) и добавить его в свои проекты .Net «Ссылки».
csc /t:library /r:System.Web.Services.dll /r:System.Xml.dll MyWebService.cs
На этом этапе вам также необходимо убедиться, что вы также включили System.Web.Services в свои «Ссылки».
Теперь вы сможете вызывать свой веб-сервис без проблем в коде.Сделать это работа вам понадобится добавить одну волшебную строку кода, прежде чем создавать экземпляр службы.
// We're using SSL here and not TLS. Without this line, nothing workie.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
Итак, я был очень впечатлен собой, поскольку тестирование на моем компьютере для разработчиков прошло отлично.Затем я выполнил развертывание на другом клиентском компьютере, и он не смог снова подключиться из-за проблемы с разрешениями/полномочиями.Для меня это пахло сертификатами (чем бы они ни пахли).Чтобы решить эту проблему, я использовал certmgr.exe зарегистрировать сертификат сайта в доверенном корне на локальном компьютере.
certmgr -add -c "c:\someDir\yourCert.cer" -s -r localMachine root
Это позволяет мне распространять сертификат на наши клиентские сайты и автоматически устанавливать его для пользователей.Я до сих пор не уверен, насколько «безопасными» будут разные версии Windows в отношении автоматической регистрации сертификатов, подобной этой, но пока это работает отлично.
Надеюсь, этот ответ поможет некоторым людям.Спасибо Blowdart за вашу помощь в этом вопросе и предоставление некоторой информации.
Другие советы
Похоже, веб-сервис использует самозаверяющий сертификат.Честно говоря, это не лучший подход.
Предполагая, что вы крупная организация и внутри нее вы можете настроить собственный доверенный центр сертификации, это особенно легко сделать с помощью Активный каталог.Из этого центра сертификации сервер, на котором размещена служба Oracle, может запросить сертификат, и вы можете использовать политику AD, чтобы доверять корневому сертификату вашего внутреннего центра сертификации, поместив его в доверенный корень машинного хранилища.Это устранит необходимость вручную доверять или принимать сертификат в веб-службе.
Если клиентские машины являются внешними, вам придется попросить людей, предоставляющих услугу, либо приобрести «настоящий» сертификат у одного из известных центров сертификации, таких как Verisign, Thawte, GeoTrust и т. д.или в рамках установки упакуйте общедоступный сертификат и установите его в доверенные корневые центры сертификации на уровне компьютера на каждом компьютере.При этом возникают проблемы, например, невозможно отозвать сертификат, но запрос будет удален.
Спасибо за этот замечательный совет, быстро осмотрелся и обнаружил, что у вас появилось много хороших идей.Вот что я хочу добавить: я разбираюсь в webMethods, и (сюрприз!) у него те же проблемы, что и у сервера приложений Oracle, к которому вы подключились (SSL3 вместо TLS).Ваш подход отлично сработал, вот мое дополнение.
Учитывая статический класс «Фабрика», предоставьте эти два удобных элемента:
/// <summary>
/// Used when dispatching code from the Factory (for example, SSL3 calls)
/// </summary>
/// <param name="flag">Make this guy have values for debugging support</param>
public delegate void CodeDispatcher(ref string flag);
/// <summary>
/// Run code in SSL3 -- this is not thread safe. All connections executed while this
/// context is active are set with this flag. Need to research how to avoid this...
/// </summary>
/// <param name="flag">Debugging context on exception</param>
/// <param name="dispatcher">Dispatching code</param>
public static void DispatchInSsl3(ref string flag, CodeDispatcher dispatcher)
{
var resetServicePoint = false;
var origSecurityProtocol = System.Net.ServicePointManager.SecurityProtocol;
try
{
System.Net.ServicePointManager.SecurityProtocol = System.Net.SecurityProtocolType.Ssl3;
resetServicePoint = true;
dispatcher(ref flag);
}
finally
{
if (resetServicePoint)
{
try { System.Net.ServicePointManager.SecurityProtocol = origSecurityProtocol; }
catch { }
}
}
}
А затем потреблять эту штуку (как вы уже наверняка догадались, но все равно сюда вставьте барабанную дробь):
var readings = new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading[] {
new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() {
attrID = 1, created = DateTime.Now.AddDays(-1), reading = 17.34, userID = 2
},
new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() {
attrID = 2, created = DateTime.Now.AddDays(-2), reading = 99.76, userID = 3
},
new ArchG2.Portal.wmArchG201_Svc_fireWmdReading.wmdReading() {
attrID = 3, created = DateTime.Now.AddDays(-5), reading = 82.17, userID = 4
}
};
ArchG2.Portal.Utils.wmArchG201.Factory.DispatchInSsl3(ref flag, (ref string flag_inner) =>
{
// creates the binding, endpoint, etc. programatically to avoid mucking with
// SharePoint web.config.
var wsFireWmdReading = ArchG2.Portal.Utils.wmArchG201.Factory.Get_fireWmdReading(ref flag_inner, LH, Context);
wsFireWmdReading.fireWmdReading(readings);
});
В этом и есть дело: когда у меня будет еще немного времени, я решу проблему с многопоточностью (или нет).
Поскольку у меня нет репутации, чтобы комментировать, я хотел бы упомянуть, что ответ Мэта Надрофски и пример кода для принудительного использования SSL3 также являются решением ошибки, похожей на
Произошла ошибка при выполнении запроса HTTP на https://xxxx/что угодно.Это может быть связано с тем, что сертификат сервера не настроен должным образом с помощью http.sys в случае HTTPS.Это также может быть вызвано несоответствием привязки безопасности между клиентом и сервером.
Просто используйте
// We're using SSL here and not TLS. Without this line, nothing workie.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
как упоминает Мат.Протестировано с сервером SAP NetWeaver PI по протоколу HTTPS.Спасибо!
Мат,
У меня тоже были такие проблемы, и у меня есть способ избежать использования certmgr.exe для добавления сертификатов в доверенный корень на удаленном компьютере.
X509Store store;
store = new X509Store("ROOT", StoreLocation.LocalMachine);
store.Open(OpenFlags.ReadWrite);
store.Add(certificate);
«Объект сертификата» можно создать следующим образом:
X509Certificate2 certificate = new X509Certificate2("Give certificate location path here");