Реализовать клиент C #, который использует WebServices через SSL? - PullRequest
13 голосов
/ 12 мая 2009

Итак, я добавил ServiceReference в консольное приложение C #, которое вызывает веб-службу, предоставляемую из Oracle.

У меня все настроено и работает как персики, когда не используется SSL (http). Я пытаюсь настроить его с помощью SSL сейчас, и у меня возникают проблемы с добавлением его в Service References (или даже Web References). Например, URL-адрес (https), на котором размещается служба, не возвращает соответствующие веб-методы, когда я пытаюсь добавить его в Visual Studio.

Базовое соединение было закрыто: при отправке произошла непредвиденная ошибка. Получен неожиданный EOF или 0 байтов из транспортного потока. Метаданные содержат ссылку, которая не может быть разрешена: 'https://srs204.mywebsite.ca:7776/SomeDirectory/MyWebService?WSDL'

Еще одно затруднение, которое у меня есть, касается управления сертификатами и их развертывания. У меня есть около 1000 внешних клиентских сайтов, которым потребуется использовать эту маленькую утилиту, и им потребуется сертификат, установленный в соответствующем хранилище сертификатов для подключения к веб-службе. Не уверен в лучшем подходе к этому. Они должны быть в корневом хранилище?

Я провел довольно много часов в Интернете, просматривая различные варианты, но нигде не могу получить хороший чистый ответ.

Подводя итог, у меня есть пара вопросов здесь:

1) У кого-нибудь есть хорошие ссылки по настройке веб-служб в Visual Studio, использующих SSL?

2) Как мне зарегистрировать сертификат? В каком магазине он должен существовать? Могу ли я просто использовать что-то вроде CertMgr для регистрации?

Должна быть хорошая книга / учебник / что угодно, что покажет мне общие хорошие практики по настройке чего-то подобного. Я просто не могу найти это!

Ответы [ 5 ]

30 голосов
/ 22 мая 2009

Ну, я понял это. Мне потребовалось гораздо больше времени, чем мне хотелось бы поговорить, но я хотел поделиться своим решением, поскольку это ОГРОМНАЯ моя любимая мозоль, чтобы увидеть стандарт. "О, я исправил это! Спасибо!" посты, которые заставляют всех висеть на том, что на самом деле произошло.

Зв

Основная проблема заключалась в том, что по умолчанию 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 Compiler , чтобы превратить этот прокси-класс в библиотеку (.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

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

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

4 голосов
/ 20 мая 2009

Похоже, веб-сервис использует самозаверяющий сертификат. Честно говоря, это не лучший подход.

Предполагая, что вы большая организация и она внутренняя, вы можете настроить собственный доверенный центр сертификации, это особенно просто с Active Directory . Из этого ЦС сервер, на котором размещается служба Oracle, может запросить сертификат, и вы можете использовать политику AD, чтобы доверять корневому сертификату вашего внутреннего ЦС, поместив его в доверенный корень хранилища компьютеров. Это избавит от необходимости вручную доверять или принимать сертификат в веб-сервисе.

Если клиентские машины являются внешними, вам нужно будет заставить людей, предоставляющих услугу, либо приобрести «настоящий» сертификат в одном из известных центров сертификации, таких как Verisign, Thawte, GeoTrust и т. Д., Либо в рамках Ваша установка связывает публичный сертификат и устанавливает его в центры сертификации Trusted Root на уровне компьютера на каждом компьютере. Это имеет проблемы, например, нет способа отозвать сертификат, но удалит приглашение.

1 голос
/ 24 января 2011

Поскольку у меня нет репутации, чтобы комментировать, я хотел бы упомянуть, что ответ Мата Надрофски и пример кода для принудительного применения SSL3 также являются решением для ошибки, подобной

Произошла ошибка при создании HTTP-запрос к https://xxxx/whatever. Это может быть связано с тем, что сертификат сервера не настроен правильно с HTTP.SYS в HTTPS дело. Это также может быть вызвано несоответствие привязки безопасности между клиентом и сервером.

Просто используйте

// We're using SSL here and not TLS. Without this line, nothing workie.
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;

как упомянуто Матем. Протестировано с сервером SAP NetWeaver PI в HTTPS. Спасибо!

1 голос
/ 22 ноября 2010

Спасибо за этот замечательный совет, быстро осмотрел ваши вещи, и у вас появилось много хороших идей. Вот немного, что я хочу добавить - я разбираюсь с 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);
    });

Вот в чем дело - когда у меня будет больше времени, я решу проблему с потоками (или нет).

1 голос
/ 29 июля 2009

Mat,

У меня тоже были такие проблемы, и у меня есть способ избежать использования 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");
...