среда, 13 апреля 2011 г.

Играем в SOAP клиента CURL`ём и игнорируем SSL сертификат

Сегодня я тестировал один очень удалённый Web Service, и мне понадобилось сделать странные вещи. Во-первых, отменить проверку SSL сертификата в клиенте, написанном на C#. Во-вторых, отправить вручную сформированный SOAP запрос.


Странная вещь №1. Зачем проверять сертификат? Мы уверены - он некорректный!
Первым делом я быстро набросал простейшего клиент Web Service`а на C#, запустил его и тут же получил по рукам: SSL сертификат был совершенно невалидный. Он был self signed, давно устарел и вообще выписан на другой хост. Позвать Web Service мучительно хотелось. А поскольку до этого мне попадались либо только свои, либо только приличные Web Service`ы, то я полез в документацию на предмет поиска атрибута, позволяющего ослабить уровень проверки.

Атрибута в документации не нашлось. Нашлось большее - делегат, позволяющий задать свою процедуру проверки сертификата, располагающийся в классе System.Net.ServicePointManager:
public static RemoteCertificateValidationCallback ServerCertificateValidationCallback { get; set; }

Тип делегата описан в пространстве имён System.Net.Security следующим образом:
public delegate bool RemoteCertificateValidationCallback(
    Object sender,
    X509Certificate certificate,
    X509Chain chain,
    SslPolicyErrors sslPolicyErrors
);

Если функция проверки принимает решение, что сертификат корректен, она должна вернуть true. Таким образом, чтобы полностью отменить проверку, естественно только в тестовых целях, необходимо сделать следующее:
ServicePointManager.ServerCertificateValidationCallback = delegate (
    Object sender,
    X509Certificate certificate,
    X509Chain chain,
    SslPolicyErrors sslPolicyErrors)
    {
        // Yes, I know it is very-very bad and strange,
        // but I need this for testing purposes...

        return true;
    };


Странная вещь №2. Я генерирую SOAP-запросы блокнотом, а вы?
Не спрашивайте, зачем мне это понадобилось, но вторая странная вещь заключалась в необходимости сформировать и отправить Web Service`у синтаксически неверный SOAP запрос. Естественно ни одна из имеющихся у меня в наличии библиотек для написания Web Service`ов: ни .NET Web Services, ни gSOAP, ни Axis - такую вольность мне не позволила. Тогда я обратил внимание на универсальное средство для отправки некорректных запросов - curl.

Действительно, ведь чем, по сути, является SOAP запрос? Это всего лишь XML документ, переданный Web Service`у по HTTP методом POST. Всё дело в волшебных заголовках. Ключевым из них является заголовок SOAPAction, который принимает строку вида "<WebServiceURL>/<CallingMethodName>". Справедливости ради необходимо отметить, что некоторый Web Service`ы, судя по всему написанные на Axis`е, полностью игнорируют это значения, проверяя лишь факт наличия данного заголовка. Так или иначе, но полная команда для отправки SOAP запроса, написанного в блокноте и сохранённого в файл InvalidRequest.xml выглядит так:
C:\>curl.exe -i -H "Content-Type: text/xml; charset=utf-8" -H "SOAPAction: https://neverhood.org/webservice/EchoService/echo" -d@InvalidRequest.xml -v https://neverhood.org/webservice/EchoService

Комментариев нет:

Отправить комментарий