Проблемы с использованием GSoap и SSL

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

Единственное изменение, которое я внес в код поддержки https, заключалось в добавлении следующего при запуске:

 soap_ssl_init();   
 if(soap_ssl_client_context(&_tradeService, SOAP_SSL_SKIP_HOST_CHECK, NULL, NULL, NULL, NULL, NULL)) {
     handleError("Failed to set up SSL connection");
     return;
 }

Если у меня включен флаг -DDEBUG, я получаю сообщение об ошибке в отношении сертификатов: «Ошибка проверки SSL или предупреждение с сертификатом на глубине 2: самозаверяющий сертификат в цепочке сертификатов», что не приводит к тому, что soap_ssl_client_context возвращает ошибку, и я не думаю, это очень важно, так как пока я тестирую, я не особо забочусь об аутентификации хоста.

Настоящая проблема заключается в этой ошибке:

Ошибка SOAP 1.2: SOAP-ENV:Sender [без субкода] «Невозможно обработать запрос без допустимого параметра действия. Укажите допустимое действие мыла».

который я получаю, когда пытаюсь сделать запрос в службу. Если я посмотрю журнал отправки, который генерирует gsoap, я увижу параметр SoapAction, установленный в исходящем заголовке. Фактически, если я сравниваю журналы отправки для служб http/https, единственная разница заключается в том, что URL-адреса для защищенной службы имеют префикс https.

Затем я подумал, что, возможно, что-то не так с сервером, поэтому я использовал curl для отправки тех же данных XML, которые gsoap зарегистрировал, с теми же заголовками. Это отлично работает, я вижу нормальный ответ с ожидаемыми данными. Это наводит меня на мысль, что, может быть, я неправильно настраиваю SSL?

Другая проблема, с которой я столкнулся, которой не было в документации, заключалась в том, что при сборке с флагами -DWITH_OPENSSL -lgsoapssl++ -lssl -lcrypto я все еще получал ошибки компоновщика о методах ssl gsoap. Мне пришлось включить stdsoap2_ssl_cpp.cpp в свою сборку, чтобы решить эти проблемы, что мне показалось странным.

Кто-нибудь пытался сделать это до этого, может дать мне несколько советов?


person Paul D.    schedule 11.12.2009    source источник


Ответы (2)


Похоже, мы боремся с похожими проблемами одновременно.

Позвольте мне начать с этого в первую очередь:

Другая проблема, с которой я столкнулся, которой не было в документах, заключалась в том, что при сборке с флагами -DWITH_OPENSSL -lgsoapssl++ -lssl -lcrypto я все еще получал ошибки компоновщика о методах ssl gsoap. Мне пришлось включить stdsoap2_ssl_cpp.cpp в мою сборку, чтобы решить эти проблемы, что мне показалось странным.

К вашему сведению: я использую VirtualBox, Ubuntu 14.04. Я скомпилировал Gsoap 2.8.21 из исходного кода с флагами --enable-debug и --with-openssl=/opt/libraries/openssl/build/1.0.1j.

Как видите, я также скомпилировал openssl из исходников, чтобы получить архивы libssl.a и libcrypto.a. Дополнительно я скомпилировал zlib, чтобы получить архив libz.a. Со всеми на месте:

  • Я сгенерировал заголовочный файл из WSDL с помощью команды:

    wsdl2h -v -g -o temporary.h https://something.com?wsdl
    
  • Добавил эту строку во временный.h перед генерацией прокси-классов:

    #import "wsse.h"
    
  • Сгенерированные клиентские классы прокси C++ с помощью команды:

    soapcpp2 -1 -I/opt/libraries/gsoap/build/2.8.21/share/gsoap/import -C -j temporary.h
    
  • С использованием QT Creator (обычный проект, к сожалению, без cmake) мой файл project.pro выглядел так:

    TEMPLATE = app
    CONFIG += console
    CONFIG -= app_bundle
    CONFIG -= qt
    
    QMAKE_CXXFLAGS += -DWITH_OPENSSL
    QMAKE_CXXFLAGS += -DWITH_DOM
    QMAKE_CXXFLAGS += -DDEBUG
    
    QMAKE_CFLAGS += -DWITH_OPENSSL
    QMAKE_CFLAGS += -DWITH_DOM
    QMAKE_CFLAGS += -DDEBUG
    
    SOURCES += main.cpp \
        soapBasicHttpBinding_USCOREIBarcodeWebServiceProxy.cpp \
        soapC.cpp \
        ../../../opt/libraries/gsoap/build/2.8.21/share/gsoap/plugin/wsseapi.cpp \
        ../../../opt/libraries/gsoap/build/2.8.21/share/gsoap/plugin/mecevp.c \
        ../../../opt/libraries/gsoap/build/2.8.21/share/gsoap/plugin/smdevp.c \
    
    HEADERS += \
        BasicHttpBinding_USCOREIBarcodeWebService.nsmap \
        soapBasicHttpBinding_USCOREIBarcodeWebServiceProxy.h \
        soapStub.h \
        soapH.h
    
    include(deployment.pri)
    qtcAddDeployment()
    
    INCLUDEPATH += ../../../opt/libraries/gsoap/build/2.8.21-debug/share/gsoap
    
    unix:!macx: LIBS += -L$$PWD/../../../opt/libraries/gsoap/build/2.8.21-debug/lib/ -lgsoapssl++
    INCLUDEPATH += $$PWD/../../../opt/libraries/gsoap/build/2.8.21-debug/include
    DEPENDPATH += $$PWD/../../../opt/libraries/gsoap/build/2.8.21-debug/include    
    unix:!macx: PRE_TARGETDEPS += $$PWD/../../../opt/libraries/gsoap/build/2.8.21-debug/lib/libgsoapssl++.a
    
    unix:!macx: LIBS += -L$$PWD/../../../opt/libraries/openssl/build/1.0.1j/lib/ -lssl
    INCLUDEPATH += $$PWD/../../../opt/libraries/openssl/build/1.0.1j/include
    DEPENDPATH += $$PWD/../../../opt/libraries/openssl/build/1.0.1j/include
    unix:!macx: PRE_TARGETDEPS += $$PWD/../../../opt/libraries/openssl/build/1.0.1j/lib/libssl.a
    
    unix:!macx: LIBS += -L$$PWD/../../../opt/libraries/openssl/build/1.0.1j/lib/ -lcrypto
    INCLUDEPATH += $$PWD/../../../opt/libraries/openssl/build/1.0.1j/include
    DEPENDPATH += $$PWD/../../../opt/libraries/openssl/build/1.0.1j/include
    unix:!macx: PRE_TARGETDEPS += $$PWD/../../../opt/libraries/openssl/build/1.0.1j/lib/libcrypto.a
    
    unix:!macx: LIBS += -L$$PWD/../../../opt/libraries/zlib/build/1.2.8/lib/ -lz
    INCLUDEPATH += $$PWD/../../../opt/libraries/zlib/build/1.2.8/include
    DEPENDPATH += $$PWD/../../../opt/libraries/zlib/build/1.2.8/include
    unix:!macx: PRE_TARGETDEPS += $$PWD/../../../opt/libraries/zlib/build/1.2.8/lib/libz.a
    
    LIBS += -ldl
    

И отвечая на вашу первую часть вопроса сейчас, я думаю, что следующие руководства должны решить проблемы, с которыми вы сейчас сталкиваетесь:

К вашему сведению: в файл main.cpp я включил:

#include <iostream>
#include "BasicHttpBinding_USCOREIBarcodeWebService.nsmap"
#include "soapBasicHttpBinding_USCOREIBarcodeWebServiceProxy.h"
#include "soapStub.h"
#include "soapH.h"
#include "plugin/wsseapi.h"

И позже в файле я добавил:

// creating empty soap struct with SOAP_IO_FLUSH
soap *soap = soap_new();
// setting flags: SOAP_SSL_REQUIRE_SERVER_AUTHENTICATION | SOAP_TLSv1
soap->ssl_flags = SOAP_SSL_DEFAULT;
// registering plugin
soap_register_plugin(soap, soap_wsse);
// file with CA certs of peers (downloaded https://www.cs.fsu.edu/~engelen/cacerts.pem.zip)
soap->cafile = "cacerts.pem";
// I placed cacerts.pem file in the same folder where your program executable will be created

Итак, возвращаясь к вашему случаю, я думаю, что в методе, который вы используете soap_ssl_client_context, один из параметров также отвечает за настройку местоположения cacerts.pem.

Если это по-прежнему не работает, вы всегда можете установить для ssl_flags значение SOAP_SSL_NO_AUTHENTICATION.

Я не знаю, может ли это решить эту проблему:

Ошибка SOAP 1.2: SOAP-ENV:Sender [без субкода] «Невозможно обработать запрос без допустимого параметра действия. Укажите допустимое действие мыла».

Однако может быть случай с прикреплением правильного файла из плагинов gsoap. Я играл с SOAP 1.1 и отключал генерацию клиентских классов прокси для SOAP 1.2.

В любом случае, я с нетерпением жду вашего ответа. Надеюсь, я смог немного помочь вам и избавить вас от многих разочарований, впервые имея дело с Gsoap :)

person Sinevar    schedule 12.01.2015

Если у меня включен флаг -DDEBUG, я получаю сообщение об ошибке о сертификатах: «Ошибка проверки SSL или предупреждение с сертификатом на глубине 2: самозаверяющий сертификат в цепочке сертификатов», что не приводит к тому, что soap_ssl_client_context возвращает ошибку, и я не Не думаю, что это очень важно, так как пока я тестирую, я не особо забочусь об аутентификации хоста.

Эта ошибка может не исчезнуть, если вы удалите -DDEBUG для использования в рабочей среде. Вы можете принимать самоподписанные сертификаты, добавив обратный вызов проверки:

soap->fsslverify = verify_callback;

int ssl_verify_callback(int ok, X509_STORE_CTX *store)
{
  if (!ok)
  {
    int err = X509_STORE_CTX_get_error(store);
    switch (err)
    {
      case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
        X509_STORE_CTX_set_error(store, X509_V_OK);
        ok = 1;
        break;
    }
  }
  return ok;
}

Ошибка SOAP 1.2: SOAP-ENV:Sender [без субкода] «Невозможно обработать запрос без допустимого параметра действия. Укажите допустимое действие мыла».

Действие SOAP может отсутствовать в заголовке HTTP/S или быть неверным по какой-либо причине. Это действие SOAP должно быть определено в WSDL и специфично для каждой вызываемой операции службы.

Чтобы установить параметр действия SOAP в заголовке HTTP/S, обязательно передайте либо NULL, либо строку действия SOAP в качестве третьего аргумента при выполнении вызова:

soap_call_SomeMethod(soap, "endpoint URL", "SOAP Action string", ...);

Когда вы передаете NULL, будет использоваться строка действия SOAP, определенная в WSDL. Проверьте код, сгенерированный wsdl2h, на предмет того, что в нем говорится об использовании операции службы в качестве действия SOAP. Действие SOAP на самом деле не требуется для служб gSOAP, но для других служб, например. WCF выдаст вам ошибки.

При использовании прокси-объекта C++ приведенный выше вызов заменяется простым вызовом метода:

proxy.SomeMethod("endpoint URL", "SOAP Action string", ...);

Если вы хотите использовать конечную точку, определенную WSDL, и действие SOAP, пропустите эти параметры:

proxy.SomeMethod(...);

Это все.

person Dr. Alex RE    schedule 05.07.2017