使用GSoap和SSL时遇到问题

时间:2009-12-11 18:45:26

标签: soap ssl openssl gsoap

我正在针对具有标准http和https版本的服务编写gSoap客户端应用程序。到目前为止,我写的所有内容都可以正常使用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:证书链中的自签名证书”,这不会导致{{1}返回错误,我认为这不是一个大问题,因为我在测试时并不真正关心验证主机。

真正的问题是这个错误:

  

SOAP 1.2错误:SOAP-ENV:发件人[没有   子代码]“无法处理请求   没有有效的动作参数。   请提供有效的肥皂行动。“

当我尝试向服务提出请求时,我得到了

。如果我查看gsoap生成的发送日志,我会看到传出标头中设置的SoapAction参数。事实上,如果我比较http / https服务的发送日志,唯一的区别是安全服务的网址以https为前缀。

然后我想也许有些东西搞砸了服务器,所以我使用curl发送与gsoap记录的完全相同的XML数据,并使用完全相同的标头。这工作正常,我看到我期望的数据的正常响应。这让我相信也许我错误地设置了SSL?

我遇到的另一个问题不是在文档中,当我使用soap_ssl_client_context标记构建时,我仍然遇到关于gsoap的ssl方法的链接器错误。我必须在我的构建中包含-DWITH_OPENSSL -lgsoapssl++ -lssl -lcrypto以便解决这些问题,我认为这很奇怪。

之前有人试过这样做可以给我一些指示吗?

2 个答案:

答案 0 :(得分:0)

看起来我们正在同时解决类似的问题。

首先让我先谈谈这个问题:

  

我在文档中没有的另一个问题是,当我建立时   使用-DWITH_OPENSSL -lgsoapssl ++ -lssl -lcrypto标记我还是   获取有关gsoap的ssl方法的链接器错误。我必须包括   我的构建中的stdsoap2_ssl_cpp.cpp是为了解决这些问题   我觉得很奇怪。

仅供参考:我使用的是VirtualBox,Ubuntu 14.04。我使用标志 - enable-debug - with-openssl = / opt / libraries / openssl / build / 1.0.1j 从源代码编译Gsoap 2.8.21。

如您所见,我还从源代码编译了openssl,以获取 libssl.a libcrypto.a 存档。另外,我编译了zlib以获取 libz.a 存档。所有这些都到位了:

  • 我使用命令:

    从WSDL生成头文件
    wsdl2h -v -g -o temporary.h https://something.com?wsdl
    
  • 在生成代理类之前,将此行添加到temporary.h中:

    #import "wsse.h"
    
  • 使用命令生成C ++代理客户端类:

    soapcpp2 -1 -I/opt/libraries/gsoap/build/2.8.21/share/gsoap/import -C -j temporary.h
    
  • 使用QT Creator(Plain Project,遗憾的是没有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:发件人[无子代码]&#34;无法处理请求   没有有效的动作参数。请提供有效的肥皂活动。&#34;

但是可能存在从gsoap插件附加正确文件的情况。我正在使用SOAP 1.1并禁用为SOAP 1.2生成代理客户端类。

无论如何,我期待你的回应。希望我能帮助你一点,并在第一次与Gsoap交易时节省很多挫折:)

答案 1 :(得分:0)

  

如果我打开了-DDEBUG标志,则会收到有关证书的错误:&#34; SSL验证错误或警告,证书深度为2:证书链中的自签名证书&#34;哪个不会导致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:发件人[无子代码]&#34;无法处理没有有效操作参数的请求。请提供有效的肥皂活动。&#34;

HTTP / S标头中可能缺少SOAP操作,或者由于某种原因导致SOAP操作不正确。此SOAP Action应在WSDL中定义,并且特定于调用的每个服务操作。

要在HTTP / S标头中设置SOAP Action参数,请确保在进行调用时将NULL或SOAP Action字符串作为第三个参数传递:

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

传递NULL时,将使用WSDL中定义的SOAP Action字符串。检查wsdl2h生成的代码,了解服务操作用作SOAP Action的内容。使用gSOAP服务并不需要SOAP Action,但其他服务例如WCF会向您抛出错误。

使用C ++代理对象时,上面的调用将被简单的方法调用替换:

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

如果要使用WSDL定义的端点和SOAP操作,请省略以下参数:

proxy.SomeMethod(...);

这就是全部。