Исключение System.Net.WebException при использовании веб-службы через HTTPS

При обращении к веб-службе, запущенной на сервере с использованием HTTPS, мое приложение выдает сообщение System.Net.WebException с сообщением "Основное соединение было закрыто: не удалось установить доверительные отношения с удаленным сервером". Я не уверен, как обойти эту проблему и успешно выполнить вызов.

Ответ 1

После некоторого исследования я нашел запись в блоге Jan Tielens, в которой объясняется, что происходит, и обходной путь для моей проблемы:

Когда вы переходите на сайт HTTPS, вы, вероятно, получите диалоговое окно с запросом, хотите ли вы доверять сертификату, предоставленному веб-сервером. Таким образом, ответственность за принятие сертификата обрабатывается пользователем. Вернитесь к сценарию webservice, если вы хотите вызвать веб-сервис, расположенный на веб-сервере, который использует SSL и HTTPS, существует проблема. Когда вы вызываете код из кода, диалоговое окно не появляется, и вы спрашиваете, доверяете ли вы сертификату (к счастью, потому что это было бы довольно уродливым в сценариях на стороне сервера); вероятно, вы получите следующее исключение:

Необработанное исключение типа System.Net.WebException произошло в System.dll
  Дополнительная информация:   соединение было закрыто: не удалось   установить доверительные отношения с   удаленный сервер.

Но есть решение для этого проблемы, вы можете решить это в своем кода, создав собственный CertificatePolicy класс (который реализует ICertificatePolicyинтерфейс). В этом классе вы будете придется писать свои собственные CheckValidationResult, которая должен возвращать true или false, как вы нажмите да или нет в диалоговом окне окно. В целях развития я создал следующий класс, который принимает все сертификаты, поэтому вы не будете получить неприятный WebException больше:

public class TrustAllCertificatePolicy : System.Net.ICertificatePolicy
{
    public TrustAllCertificatePolicy() { }

    public bool CheckValidationResult(ServicePoint sp, X509Certificate cert, WebRequest req, int problem)
    {
        return true;
    }
}

Как вы можете видеть CheckValidationResult функция всегда возвращает true, поэтому все сертификаты будут быть доверенным. Если вы хотите сделать это класс немного более безопасен, вы может добавить дополнительные проверки, используя X509Certificate, например. Чтобы использовать этот CertificatePolicy, вы должны сообщить ServicePointManagerиспользовать его:

System.Net.ServicePointManager.CertificatePolicy = new TrustAllCertificatePolicy();

Это должно быть сделано (один раз в течение жизненного цикла приложения), прежде чем вызов вашего веб-сервиса.

Ответ 2

Если вы используете самоподписанный SSL-сертификат или ненадежный SSL-сертификат, вы можете сказать своему приложению игнорировать его (если вы действительно хотите его игнорировать). например.

ServicePointManager.ServerCertificateValidationCallback = _
      new RemoteCertificateValidationCallback(IgnoreSelfSSL)

public bool IgnoreSelfSSL(ServicePoint sp, X509Certificate cert,WebRequest req, int problem) { 
   return true; 
}

Вы можете поместить обратный вызов в любом месте, которое будет удалено до выполнения вашего служебного вызова.

Ответ 3

Рекомендации, приведенные в ответах, следует использовать только для тестирования. Для принятия/производства у вас должен быть установлен WS-сертификат на вызов компьютера на WS и проверка сертификата перед вызовом WS-expiration, subject и т.д. Затем вы можете добавить этот сертификат к WS-запросу через SoapHttpClientProtocol.Proxy.ClientCertificates.