gsoap域名空间从哪买怎么改变

gSoap使用实例(转)
(基于gsoap-win32-2.7版本,编译环境为VS2005)
访问自己定义的一个WebService(命名为AddService,对输入的两个整形参数求和,具体服务定义参见
AddService.wsdl)
wsdl2h.exe -s -o AddService.h AddService.wsdl
生成具体调用代码
在命令行输入soapcpp2.exe -C AddService.h
生成代码后,AddService.h就没有用了,不用加入到工程中。
生成的文件
soapStub.h
soapAddServiceSoapBindingProxy.h:封装了调用webservice的类
soapClientLib.cpp:用不到
soapClient.cpp
AddServiceSoapBinding.nsmap:namespaces声明,需要包含在一个cpp文件里面,比如放在
StdAfx.cpp里面,否则连接时报错:unresolved external symbol _namespaces
还需要stdsoap2.cpp和stdsoap2.h文件,在gsoap-2.7soapcpp2目录下。
注意:#include “StdAfx.h”加到第一行,否则VC编译报错:fatal error C1010:
unexpected end of file while looking for precompiled header
实际调用代码
将这些文件加入到C++工程中,可以使用以下代码调用WebService:
//&包含代理类的头文件#include&"gSoap\soapAddBindingProxy.h"
声明访问代理对象
AddBinding
设置访问的WebServiceURL
serviceBinding.endpoint&=&("http://LocalHost:8082/");
nRetCode&=&serviceBinding.__ns1__AddOperation(12,&22,iResult);
实现AddService(对输入的两个整形参数求和)
生成调用代码
同客户端生成方法基本一致。需要注意的是以下几点:
由.h文件生成具体调用代码:soapcpp2.exe -S AddService.h
soapClient.cpp soapClientLib.cpp
soapServerLib.cpp这三个文件不需要加入到C++工程中。
实现服务线程
在程序开始时,启动服务线程。
GSoapServiceThreadFunc(LPVOID p)
定义编码格式
//&设置UTF-8编码方式
soap_set_mode(&soap, SOAP_C_UTFSTRING);
设置服务的端口号
//&端口号int&port&=&8083;
int&backlog&=&100;&//
int&m&=&soap_bind(&soap,
NULL, port, backlog);if(m&&&/span&&0)
strOutput.Format(_T("GSoapServiceThreadFunc——在端口%d上启动服务失败!"),
OutputDebugString(strOutput);
soap_done(&soap);&//&close
master socket and detach
environment&&&&&&&&
soap.accept_timeout&=&5;//&设置GSoap连接超时,单位:秒
创建循环,监听,如果有新连接进来则创建请求处理现场
while(TRUE)
WaitForSingleObject(g_eventTerminateService.m_hObject,&0)&==&WAIT_OBJECT_0
&&&&//&结束GSoap服务线程
&&&&&&&&break;
&&&&int&s&=&soap_accept(&soap);
&&&&if(&!soap_valid_socket(s)
&&&&&&&&if(
soap.errnum )
&&&&&&&&&&&&
soap_print_fault(&soap, stderr);
&&&&&&&&&&&&
soap_done(&soap);&//&close
master socket and detach
environment&&&&&&&&&&&&
strOutput.Format(_T("\nGSoapServiceThreadFunc——等待客户端连接超时!"));
OutputDebugString(strOutput);
strOutput.Format(_T("\n收到来自于IP地址%d.%d.%d.%d的socket连接%d!"),
(soap.ip&&&24)&0xFF,
(soap.ip&&&&16)&0xFF,
(soap.ip&&&&8)&0xFF,
soap.ip&0xFF, s);
OutputDebugString(strOutput);
&&&&&&&&struct&soap*&tsoap&=&soap_copy(&soap);&//&make
a safe copy&&&&&&&&
&&&&&&&&if(&!tsoap
&&&&&&&&&&&&break;
AfxBeginThread(process_request, tsoap);
实现请求处理线程
///&GSoap请求处理线程
process_request(LPVOID soap)
CoInitialize(NULL);
soap_serve((struct&soap*)soap);&&&&&//&会自动调用具体的接口函数
soap_destroy((struct&soap*)soap);&&&&&&&//&dealloc
C++ data&&&&
soap_end((struct&soap*)soap);&&&&&&&&&&&//&dealloc
data and clean up&&&&
soap_done((struct&soap*)soap);&&&&&&&&&&//&detach
soap struct&&&&
free(soap);
CoUninitialize();
&&&&return&0;
实现接口功能函数
在代码中定义相应的接口功能函数
int&__ns1__AddOperation(struct&soap*,&int&A,&int&B,&int&&result)
result&=&A&+&B;
&&&&return&SOAP_OK;
函数原型在soapStub.h中定义
SOAP_FMAC5&int&SOAP_FMAC6
__ns1__AddOperation(struct&soap*,&int&A,&int&B,&int&&result);
现在采用的是默认的命名空间前缀,可以使用typemap.dat文件赋予自定义的命名空间。
支持访问wsdl
首先要设置回调处理函数
soap.fget&=&http_
soap.fpost&=&http_
两个回调函数的接口定义(stdsoap2.h)
int&(*fpost)(struct&soap*,&const&char*,&const&char*,&int,&const&char*,&const&char*,
size_t);int&(*fget)(struct&soap*);
根据接口定义实现相应的函数
int&http_post(struct&soap&*soap,&const&char&*endpoint,&const&char&*host,&int&port,const&char&*path,const&char&*action,
size_t count)
&&&&&&&&return&http_get(
);&//&简单处理,直接调用http_get
int&http_get(struct&soap&*soap)
在http_get函数中解析外部访问路径,并且获取相应的wsdl文件名
//&请求WSDL时,传送相应文件//&获取请求的wsdl文件名
string&fielPath(soap-&path);
size_t pos&=&fielPath.rfind("/");
string&fileName(fielPath,
//&将?替换为.
dotPos&=&fileName.rfind("?");
if(dotPos&==&-1)
&&&&&&&&//&未找到
&&&&&&&&return&404;
fileName.replace(dotPos,1,&".");
打开WSDL文件发送到客户端
//&打开WSDL文件准备拷贝
FILE*&fd&=&fopen(fileName.c_str(),&"rb");
&&&&//&return
HTTP not found error&&&&return&404;
//&HTTP header
with text/xml contentsoap-&http_content&=&"text/xml";
soap_response(soap,
SOAP_FILE);for(;;)
&&&&&&&&//&从fd中读取数据
size_t r&=&fread(soap-&tmpbuf,&1,&sizeof(soap-&tmpbuf),
&&&&&&&&if&(!r)
&&&&&&&&&&&&&&&&break;
&&&&&&&&//&发送数据
&&&&&&&&if&(soap_send_raw(soap,
soap-&tmpbuf, r))
&&&&&&&&&&&&&&&&//&can't
send, but little we can do about
that&&&&&&&&&&&&&&&&break;
fclose(fd);
soap_end_send(soap);
return&SOAP_OK;
修改命名空间前缀
修改gSoapServer工程使用的命名空间前缀。在wsdl中的命名空间为“”
在typemap.dat文件最后添加一行
NSNEW="http://new.webservice.namespace"
转换wsdl文件时添加参数
wsdl2h.exe -t typemap.dat -s -o AddService.h AddService.wsdl
查看函数原型(soapStub.h),可以看到前缀已经被改变
SOAP_FMAC5&int&SOAP_FMAC6
__NSNEW__AddOperation(struct&soap*,&int&A,&int&B,&int&&result);
前段时间学习了一段时间的gsoap,&
在网上查找了资料,很多资料都说先由wsdl文件生成.h文件,再由.h文件生成相应的soap相关的依赖文件。因此一开始花了很多时间去研究wsdl怎样写。走入了一个误区。昨天看到一篇文章后才明白,一开始我就走入了误区。wsdl是通过gsoap自动生成的。
也就是说再没有wsdl文件的时候可以先定义xxxx.h文件,xxxx.h的定义里面要添加一些说明的语句
//gsoap ns service name: severName
等项。然后通过soapcpp2.exe& xxxx.h来生成wsdl文件等。
如果有可以利用的wsdl文件则可以先生成.h文件再生成soap依赖文件,如:soapStub.h等。
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。gsoap之soap版本不匹配 - CSDN博客
gsoap之soap版本不匹配
问题背景:
WCF server with basicHttpBinding use soap1.1, while gSoap generates client that uses soap1.2.
所以WCF server 和 gSoap产生的 client端之间通讯的soap message format不匹配。当客户端发起请求时,server端无法识别请求。
解决办法:
gSoap 生成的代码中,删除所有的soap1.2 namespace,换上对应的saop 1.1 namespace.
对于所有的gSoap工具生成的*Proxy.cpp 文件和*.nsmp文件,都要按如下格式将其中的soap 1.2 namespace 换成 soap 1.1 namespace.
{&SOAP-ENV&, &&, &&,
{&SOAP-ENC&, &&, &&,
{&xsi&, &&, &&,
{&xsd&, &&, &&, NULL},
{&SOAP-ENV&, &&, NULL, NULL},
{&SOAP-ENC&, &&, NULL, NULL},
{&xsi&, &&, NULL, NULL},
{&xsd&, &&, NULL, NULL},
本文已收录于以下专栏:
相关文章推荐
gSOAP 安装过程
操作系统:CentOS 6.3
gSOAP:gsoap_2.8.17.zip
1. 解压 gsoap_2.8.17.zip,进入 gsoap-2.8 目...
网上的向导文档:/doc/soapdoc2.html#tth_sEc7.2.7
官方工具:http://download.csdn.net/d...
这篇主要是对gsoap编程的一个简单介绍,以及消息结构的简单那剖析,最后简单介绍了一下discover的实现。
(三)gsoap编程简述
    这一部分只是对gsoap最基本的框架做个简单的介绍,并...
SOAP_NMAC struct Namespace namespaces[] =
{&SOAP-ENV&, &http://www.w3.org/2003/05/soap-envelope&,...
gsoap namespace 修改
作者:蒋呈蔚
 使用webservice接口的连接,首先需要一个.WSDL文件,一般就是供应方提供的网页链接,直接用IE打开然后另存就是我们需要...
gSOAP2.8.30 的下载地址:/downloads.html
我的linux发行版本是ubuntu 10.04,在linux上安装gSOAP不能用...
gsoap 服务端 客户端 多线程
用gSOAP开发Web Service程序
gSOAP是一个绑定SOAP/XML到C/C++语言的工具,使用它可以简单快速地开发出SOAP/XML的服务器端和客户端。由于gSOAP具...
由于工作调动关系,需要了解 gSOAP 的使用,写个文章记录一下学习的心得,免得以后忘记。安装由于本人使用的是 Mac OS 系统,故以 Mac OS 为例说明如何安装 gSOAP。1)下载 gsoa...
gSOAP是一个夸平台的,用于开发Web Service服务端和客户端的工具,在Windows、Linux、MAC OS和UNIX下使用C和C++语言编码,集成了SSL功能。  下载地址:http:/...
他的最新文章
讲师:吴岸城
您举报文章:
举报原因:
原文地址:
原因补充:
(最多只允许输入30个字)通过双向证书认证使用 gSOAP 访问 web services
概述本文通过一系列的实验步骤描述,向您展示如何使用 gSOAP 编写的客户端,通过双向证书认证,访问由 tomcat7 和 Axis2 搭建的 web 服务。全文循序渐进,分为几个阶段逐步展开,每个阶段相关的注意事项和遇到过的一些问题也一并记录下来供读者参考。先简单介绍一下需要准备的工具。服务端:由 tomcat7+axis2 搭建而成客户端:由 gSOAP 工具生成证书
:用 openssl 和 jdk 自带的 keytool 制作其它
:如果在 Windows 操作系统下实验,C/C++ 代码可能还会需要一些集成开发环境,如 Visual C++2010 或 CodeBlocks+MinGW 等。Java 代码的编译可能会用到 eclipse。此外,为叙述方便,后文的用词上也作一些约定:将 tomcat7 的安装路径记为:&tomcat_home&将 gSOAP 压缩包的解压路径记为:&gsoap_home&将 openssl 的安装路径记为:&openssl_home&将基于 http 的 web 服务网址记为:&service_http&将基于 https 的 web 服务网址记为:&service_https&搭建基于 http 的 web 服务准备好 java 代码这里编写一个非常简单的 sayHello 功能的 java 代码,传入参数是一个字符串,返回值则是“Hello”加上传入的字符串。稍后用其发布 web 服务已经足够了,如
所示:清单 1. sayHello 源码 public class SimpleService{
public String sayHello(String name){
return "Hello, "+
}使用 eclipse 或者 jdk 自带的 javac 命令行工具进行编译,生成 SimpleService.class 文件。部署服务利用 SimpleService.class 文件,快速的发布一个基于 http 的 web 服务,步骤如下:从 axis2 官方网站下载 WAR (Web Archive) Distribution,例如:axis2-1.6.2-war.zip将 axis2-1.6.2-war.zip 文件解压缩,获得 axis2.war 文件;将 axis2.war 文件放置于 &tomcat_home&\webapps 下;启动 tomcat7,axis2.war 会自动解压缩生成 axis2 目录;将 SimpleService.class 放置于 &tomcat_home&\webapps\axis2\WEB-INF\pojo 下。这样,一个简单的 web 服务发布就完成了。验证的方式也很简单,打开发布服务电脑上的浏览器,查看网址 http://127.0.0.1:8080/axis2/services/SimpleService?wsdl,如果能够显示 XML 结构的内容,就说明发布成功。当然,也可以通过局域网内其它电脑访问该服务,如果访问不了,需要查看,IP 地址和端口是否正确,防火墙是否配置得当或关闭等。后文我们将这个基于 http 的 web 服务网址记为 &service_http&。值得一提的是,这里我们发布的 web 服务是通过 axis2 提供的热部署 (hotdeployment)功能进行的。打开 &tomcat_home&\webapps\axis2\WEB-INF\conf 下的 axis2.xml 文件,我们可以看到 axis2 默认是打开了热部署开关 hotdeployment 的,如
所示。图 1. axis2 热部署开关此外,pojo 部署目录也可以进行修改,如
所示:图 2. axis2 pojo 部署路径编写支持 http 方式的客户端编写客户端,首先要使用 gSOAP 提供的工具生成一些代码。gSOAP 的压缩包可以从其网站下载,例如 gsoap_2.8.9.zip,然后解压即可。后文我们将 gSOAP 压缩包的解压路径记为:&gsoap_home&。在 &gsoap_home&\gsoap\bin\ 下,已经为我们准备好了三种不同平台的代码生成工具,使用时根据自己的操作系统进行选择。如果没有合适的版本,可以根据工具源码,以及 INSTALL.txt 文件的描述,自行编译。下面描述工具的使用步骤。生成头文件在命令行中输入生成 C++ 头文件的命令:wsdl2h -o gSOAP_http.h &service_http&如果要生成 C 头文件,则需要加上 -c 选项:wsdl2h -c -o gSOAP_http.h &service_http&此外,我们也可以将 &service_http& 从浏览器中另存为本地的 XML 文件,用于上述的命令中来生成头文件。wsdl2h 命令选项比较多,除了常用的 -c – o 等选项之外,可以敲入 -h 进行详细查看。注意! 在生成代码的过程中,可能会遇到“Cannot open file ‘ typemap.dat ’”的提示,这里 typemap.dat 文件主要的作用是从 xml 格式数据转换为 C/C++ 代码时,可以自定义或优化绑定的类型。该文件可以从 &service_http&\gsoap\ 下找到。本文的实验中,不使用该文件也可以,wsdl2h 会使用内置类型进行转换。生成源文件接下来,我们利用 gSOAP_http.h 生成相关的源码。在命令行中输入生成 C++ 客户端源码的命令:soapcpp2 -C gSOAP_http.h -I &gsoap_home&\gsoap\import如果要生成 C 源码,则需要加上 -c 选项:soapcpp2 -c -C gSOAP_http.h -I &gsoap_home&\gsoap\import这里 -C 表示只生成客户端源码,-c 表示只生成 C 语言源码,-I 指明了生成源码时需要提供的头文件路径。soapcpp2 命令还有更多的选项,可以通过敲入 -h 进行详细查看。挑选有用的文件如果生成的是 C++ 源码,则需要的文件包括以下 8 个:gSOAP_http.hsoapH.hsoapStub.hSimpleServiceSoap11Binding.nsmapsoapC.cppsoapClient.cpp&gsoap_home&\gsoap\stdsoap2.h&gsoap_home&\gsoap\stdsoap2.cpp如果生成的是 C 源码,则需要的文件包括以下 8 个:gSOAP_http.hsoapH.hsoapStub.hSimpleServiceSoap11Binding.nsmapsoapC.csoapClient.c&gsoap_home&\gsoap\stdsoap2.h&gsoap_home&\gsoap\stdsoap2.c注意! 并非针对所有的 web 服务生成的文件名和数量都是固定的,例如这里会生成 SimpleServiceSoap11Binding.nsmap 和 SimpleServiceSoap12Binding.nsmap 两个文件,但有些 web 服务可能只生成一个 .nsmap 文件。编写客户端代码时要根据具体情况,进行头文件包含。编写客户端代码根据挑选好的 8 个文件,建立一个 C++ 或者 C 的工程,然后再自行建立一个包含 main() 函数的源文件:清单 2. 支持 http 方式的 C++ 客户端源码 #include "soapH.h"
#include "SimpleServiceSoap11Binding.nsmap"
int main()
struct soap
_ns1__sayHello
tSayHelloS
_ns1__sayHelloResponse
tSayHelloR
soap_init(&tClientSoap);
tSayHelloSender.args0 = new string("the beautiful world!\n");
iResult=soap_call___ns2__sayHello(&tClientSoap, NULL, NULL,
&tSayHelloSender, &tSayHelloResponse);
if(iResult==SOAP_OK)
cout&&*(tSayHelloResponse.return_)&&
cout&&"Error code "&&iResult&&
delete tSayHelloSender.args0;
soap_destroy(&tClientSoap);
soap_end(&tClientSoap);
soap_done(&tClientSoap);
}清单 3. 支持 http 方式的 C 客户端源码 #include "soapH.h"
#include "SimpleServiceSoap11Binding.nsmap"
int main()
struct soap
struct _ns1__sayHello
tSayHelloS
struct _ns1__sayHelloResponse
tSayHelloR
achName[256]="the beautiful world!\n";
soap_init(&tClientSoap);
tSayHelloSender.args0=achN
iResult=soap_call___ns2__sayHello(&tClientSoap, NULL, NULL,
&tSayHelloSender, &tSayHelloResponse);
if(iResult==SOAP_OK)
printf("%s\n",tSayHelloResponse.return_);
printf("Error code %d\n",iResult);
soap_destroy(&tClientSoap);
soap_end(&tClientSoap);
soap_done(&tClientSoap);
}编译和运行可能出现的问题除了前文所述的,需要根据具体情况调整包含的 .nsmap 文件名之外。使用 gSOAP 工具生成的头文件和源码中包含的结构体、类和函数名也是根据情况的变化而不同的(本例中是 _ns1_sayHello、_ns1_sayHelloResponse 以及 soap_call___ns2__sayHello() 函数)。通常情况下,查阅 wsdl2h 工具生成的头文件(本例中是 gSOAP_http.h 文件),就可以找到对应的声明。如果出现调用 soap 函数返回结果不是 SOAP_OK 的情况,可以根据错误码打印,在 stdsoap2.h 文件中找到对应的宏定义名。Windows 平台下:以 C++ 代码为例,可以使用 Visual Studio2010 或者 CodeBlocks+MinGW 进行编译和运行。其中,使用 CodeBlocks+MinGW 可能会遇到一些问题,例如编译的时候可能会报错“undefined reference to sendto@24'”或者“undefined reference to __imp_send”。此时需要链接库文件 libws2_32.a。Linux 平台下:以 C 代码为例,可以在源码目录下简单键入命令 gcc – o Hello *.c 生成可执行文件。如果上述步骤均无错,编译成功后运行,可以看到输出结果“Hello, the beautiful world!”制作证书前面描述了一个基于 http 方式 web 服务的搭建和访问。接下来,为了将其改造为基于 https 的通信方式,我们需要先准备好相关的证书。由于只是用于实验目的,就不向专门的 CA 认证机构申请证书了,使用 openssl 工具进行证书的制作。编译和安装 opensslWindows 平台在 Windows 平台下编译 openssl 需要确保安装有 Visual C++2005 以上版本,如果没有 perl 工具还需要安装 activeperl。编译步骤如下:打开命令行,运行 Visual C++ 安装路径下的 VC\vcvarsall.bat 文件以注册环境变量确保已将 perl.exe 所在路径添加到环境变量 PATH 中从 openssl 网站下载压缩包,例如:openssl-1.0.1c.tar.gz,然后解压从命令行进 openssl 的解压目录指定安装目录,例如 D:\ssl,输入命令 perl Configure VC-WIN32 --prefix=D:\ssl输入命令 ms\do_ms输入命令 nmake -f ms\ntdll.mak输入命令 nmake -f ms\ntdll.mak test输入命令 nmake -f ms\ntdll.mak install上述步骤完毕后,生成的内容都输出到 D:\ssl 了(实际上先是生成到解压目录下的 out32dll 子目录中的)。后文我们就将 openssl 的安装目录记为 &openssl_home&。其中,&openssl_home&\lib\ 下的 libeay32.lib 和 ssleay32.lib 就是后文进行程序的编译链接时需要的库文件。注意! 如果不严格按照上述步骤来做,容易出现一些问题。例如:使用 Visual C++6.0 版本的话,很可能会在执行 nmake -f ms\ntdll.mak 时遇到错误 NMAKE : fatal error U1077: 'ml' : return code '0x1',微软提供了一个
的下载用来修正这个问题,但实际上问题还会存在。仔细阅读微软的下载页面就会发现,这个文件是为 Visual C++2005 准备的。所以还是建议使用 Visual C++2005 以上的版本。再如:如果不是在命令行中,运行上文所述的 vcvarsall.bat 文件,就会出现 namke.exe、link.exe 等工具找不到的错误提示。即使手动将相关路径加入 PATH 环境变量,还是会出现其它文件找不到引发的错误提示。此外,设定 &openssl_home& 的时候,如果指定到根目录下,可能会提示错误,无法创建相关文件夹。如果要清理掉重新编译,先执行 nmake -f ms\ntdll.mak clean 命令。Linux 平台通常情况下 Linux 系统已经自带 openssl。可以在命令行下键入 openssl 命令进行尝试,如果提示找不到相关命令,再使用压缩包解压后进行编译和安装,过程比较简单,这里不赘述。注意!Windows 下 libeay32.lib 和 ssleay32.lib 文件,在 Linux 下对应的文件名是 libcrypto.a 和 libssl.a制作 CA 根证书从命令行进入 &openssl_home&\bin 目录,输入命令openssl req -new -x509 -keyout ca.key -out ca.crt -config ..\f这里会要求输入 key 文件保护口令,以及证书的详细信息,生成的文件包括:ca.key 该文件是 CA 私钥文件ca.crt 该文件是 CA 自签名证书,也即后面用做 CA 根证书的文件注意! 接下来制作服务端和客户端证书的时候,填写的证书详细信息,不要和 CA 证书的详细信息完全一样,否则,使用 CA 私钥进行签名时会报错:“openssl TXT_DB error number 2 failed to update database”。制作服务端证书先使用 jdk 自带的 keytool 工具,为服务端生成一个 keystore 文件。打开命令行,进入某个存放服务端证书的目录,然后输入命令:keytool -genkey -alias server -keyalg RSA -keystore server.keystore这里 keytool 也会交互的要求用户输入 keystore 文件保护口令,以及相应的证书详细信息。生成的 server.keystore 文件中,包含了服务端的一对密钥以及一个自签名证书。注意! 服务端证书详细信息中的 CommonName(名字与姓氏)要和客户端访问的 URL 域名或 IP 地址一致,否则 gSOAP 程序内部会检验不通过导致访问失败。具体情况下文会提及。由于我们要让服务端和客户端信任同一个 CA,因此这里生成的自签名证书需要替换成由
签名的证书。具体操作如下:首先,生成服务端的证书签名请求文件,输入命令keytool -certreq -alias server -sigalg MD5withRSA -file server.csr
-keystore server.keystore按照提示,输入 server.keystore 的保护口令后,生成了 server.csr然后将 server.csr 拷贝到 CA 所在电脑的 &openssl_home&\bin 目录下,输入命令:openssl ca -in server.csr -out server.crt -cert ca.crt -keyfile ca.key -notext -config ..\f注意! 这里可能会提示缺少 ./demoCA 等目录和文件。要解决这个问题,可以修改 &openssl_home&\f 中的配置,也可以在当前的 &openssl_home&\bin 下手动建立如下内容:demoCA 目录demoCA\index.txt 文件demoCA\serial 文件,并手动在里面随便填写一个合法的十六进制数值,如 0000demoCA\newcerts 目录注意 ! 这里还可能会遇到诸如“The stateOrProvinceName field needed to be the same in the CA certificate (xx) and the request (xx)”的错误。有可能 CA 证书的这个字段和服务端证书请求的这个字段确实不同,那么重新生成字段相同的文件即可。也有可能明明已经相同了,还报这个错误,这是 openssl 某些版本的 bug,可以查阅 openssl 的
页面。为解决这个问题,需要将 &openssl_home&\f 中 [ policy_match ] 下相关字段值由 match 修改为 optional。重新执行一下上述命令 , 如果顺利,就会生成服务端证书文件 server.crt。接下来,我们要将 CA 签名后的证书导入 server.keystore。方法是将 ca.crt 和 server.crt 拷贝回 server.keystore 所在电脑的目录下,输入命令:keytool -import -v -trustcacerts -alias ca -file ca.crt -keystore server.keystorekeytool -import -v -alias server -file server.crt -keystore server.keystore上述第一步,是导入 CA 根证书作为服务端的受信任 CA。第二部是导入由 CA 签名的服务端证书。注意! 这里必须先将 CA 根证书导入服务端证书所在的同一个 keystore 文件中,然后才能导入新生成的服务端证书,否则 keytool 会报错“keytool 错误: java.lang.Exception: 无法从回复中建立链接”。制作客户端证书先生成客户端私钥,在命令行中输入:openssl genrsa -des3 -out client.key 1024接着生成客户端证书签名请求文件,输入命令:openssl req -new -key client.key -out client.csr -config ..\f最后进行 CA 签名:openssl ca -in client.csr -out client.crt -cert ca.crt -keyfile ca.key -notext -config ..\f顺利的话,客户端证书文件 client.crt 就生成完毕了。注意! 我们还需要制作一个客户端证书与 key 的拼接文件,后文会使用到。简单来说就是将 client.crt 和 client.key 的内容,按顺序合成一个文件。具体合成的方法 Linux 下可以使用命令“cat client.crt client.key & client.pem”,Windows 下可以使用命令“type client.crt client.key & client.pem”,或者用文本编辑器,直接手动拼接也可以。生成的文件列表生成的和证书相关的文件。包括:ca.crtca.keyserver.keystoreserver.csrserver.crtclient.pemclient.crtclient.keyclient.csr后文中需要用到的包括:服务端需要:server.keystore客户端需要:ca.crt、client.pem搭建基于 https 的 web 服务修改 tomcat7 的配置打开 &tomcat_home&\conf\server.xml 文件,找到如
所示的片段:图 3. 修改前的 tomcat7 https 端口配置将这一段注释符去掉,使得 https 端口 8443 生效(如果找不到这一段,也可以自行添加),并添加上参数 keystoreFile 和 keystorePass,如 。图 4. 修改后的 tomcat7 https 端口配置这里假定,先前生成的
的保护口令是“server”。其中 clientAuth=”false”表示服务端不需要检查客户端证书。修改完毕后,重启 tomcat7 服务,然后可以打开网页浏览器,访问 https://127.0.0.1:8443 进行尝试,如果提示“不受信任的链接”之类的安全警报,可以点击接受信任,并继续访问,就可以看到显示有 Apache Tomcat 标志的页面了。此时还没有结束,因为我们还不能访问 axis2 提供的 web 服务。修改 axis2 的配置打开 &tomcat_home&\webapps\axis2\WEB-INF\conf\axis2.xml 文件,应该可以找到
所示的配置片段:图 5. 修改前的 axis2 配置我们在这段配置下面增加一概述段 https 的配置,如
所示:图 6. 修改后的 axis2 配置验证配置上述 tomcat7 和 axis2 的配置文件都修改完毕并保存后,重启 tomcat7 服务,然后访问地址:https://127.0.0.1:8443/axis2/services/SimpleService?wsdl,如果能够显示 XML 结构的内容,就说明发布成功。同样的,也可以通过局域网内其它电脑访问该服务,如果访问不了,需要查看,IP 地址和端口号是否正确,防火墙是否配置得当或关闭等因素。后文我们将这个基于 https 的 web 服务网址记为 &service_https&。编写支持 https 方式的客户端使用 gSOAP 生成相关文件相关的头文件的生成,以及源文件的生成方法,同前文所述。注意! 使用 wsdl2h 时,如果直接使用 &service_https&,会遇到
所示的问题,提示 wsdl2h 程序“no SSL support, please rebuild wsdl2h with SSL or download the files and rerun wsdl2h”:图 7. wsdl2h 遇到的问题按照
的提示,要么重新编译支持 SSL 的 wsdl2h 可执行文件,要么将相关文件下载下来使用。重新编译 wsdl2h 可以按照 gSOAP 相关文档进行,这里我们采用简单一点的方式,从浏览器打开 &service_https&,并另存为 SimpleService.xml 文件。注意! 保存在本地的 SimpleService.xml 文件里包含了 URL 信息,如果将其拷贝给局域网其它电脑访问 web 服务,那么另存的 URL 地址也应该有相应修改,而不能再是 127.0.0.1 了。例如
所示的是局域网的 Linux 环境下使用 wget 程序获取 &service_https& 文件的例子,使用 --no-check-certificate 选项,忽略对服务端证书的检查:图 8. 局域网用 wget 程序获取 https URL这和在本机使用浏览器,打开 非 127.0.0.1 地址的 URL 后,另存为 XML 文件,再拷贝到局域网机器上,效果是一样的。生成 C++ 相关的客户端文件命令:wsdl2h -o gSOAP_https.h SimpleService.xmlsoapcpp2 -C gSOAP_https.h -I &gsoap_home&\gsoap\import生成 C 相关的客户端文件命令:wsdl2h -c -o gSOAP_https.h SimpleService.xmlsoapcpp2 -c -C gSOAP_https.h -I &gsoap_home&\gsoap\import编写客户端代码同前文所述,挑选好所需的 8 个文件,然后建立一个 C++ 或者 C 的工程,再自行建立一个包含 main() 函数的源文件,进行测试。和 http 客户端的源码不同之处在于,https 客户端源码,需要在调用 soap_init() 后,调用 soap_ssl_client_context() 函数,这里我们暂且使用 SOAP_SSL_NO_AUTHENTICATION 参数,表示客户端不检查服务端证书。清单 4. 支持 https 方式的 C++ 客户端源码 #include "soapH.h"
#include "SimpleServiceSoap11Binding.nsmap"
int main()
struct soap
_ns1__sayHello
tSayHelloS
_ns1__sayHelloResponse
tSayHelloR
soap_init(&tClientSoap);
if(soap_ssl_client_context(&tClientSoap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, NULL, NULL, NULL, NULL))
soap_print_fault(&tClientSoap, stderr);
return -1;
tSayHelloSender.args0 = new string("the beautiful world!\n");
iResult=soap_call___ns2__sayHello(&tClientSoap, NULL, NULL,
&tSayHelloSender, &tSayHelloResponse);
if(iResult==SOAP_OK)
cout&&*(tSayHelloResponse.return_)&&
cout&&"Error code "&&iResult&&
delete tSayHelloSender.args0;
soap_destroy(&tClientSoap);
soap_end(&tClientSoap);
soap_done(&tClientSoap);
}清单 5. 支持 https 方式的 C 客户端源码 #include "soapH.h"
#include "SimpleServiceSoap11Binding.nsmap"
int main()
struct soap
struct _ns1__sayHello
tSayHelloS
struct _ns1__sayHelloResponse
tSayHelloR
achName[256]="the beautiful world!\n";
soap_init(&tClientSoap);
if(soap_ssl_client_context(&tClientSoap,
SOAP_SSL_NO_AUTHENTICATION,
NULL, NULL, NULL, NULL, NULL))
soap_print_fault(&tClientSoap, stderr);
return -1;
tSayHelloSender.args0=achN
iResult=soap_call___ns2__sayHello(&tClientSoap, NULL, NULL,
&tSayHelloSender, &tSayHelloResponse);
if(iResult==SOAP_OK)
printf("%s\n",tSayHelloResponse.return_);
printf("Error code %d\n",iResult);
soap_destroy(&tClientSoap);
soap_end(&tClientSoap);
soap_done(&tClientSoap);
}Windows 平台下的编译和运行Windows 平台下以
的 C++ 代码的编译为例。使用 CodeBlocks+MinGW 编译的步骤为:在工程标签上右键选择 Build Option找到 Compiler settings 标签下的 #defines 标签,加入宏 WITH_OPENSSL(没有这个宏定义,编译器不会编译 soap_ssl_client_context() 函数)找到 Linker settings 标签,添加上 MinGW 自带的 libws2_32.a 库文件(没有这个文件会出现找不到 sendto() 等函数的问题)依然是 Linker settings 标签,添加上 &openssl_home&\lib 下的 libeay32.lib 和 ssleay32.lib找到 Search directories 标签下的 Compiler 标签,添加上 &openssl_home&\include(不是 &openssl_home&\include\openssl,因为 stdsoap2.h 文件包含头文件的时候已经将 openssl 子目录考虑进去了)再将 &openssl_home&\bin 目录下 libeay32.dll 和 libeay32.dll 拷贝到将生成可执行文件的路径下。使用 Visual Studio2010 编译的步骤为:在工程标签上右键选择属性在属性页面的“C/C++ --& 预处理器 --& 预处理器定义”中添加上 WITH_OPENSSL(没有这个宏定义,编译器不会编译 soap_ssl_client_context() 函数)在属性页面的“链接器 --& 输入 --& 附加依赖项”中添加上 &openssl_home&\lib 下的 libeay32.lib 和 ssleay32.lib在属性页面的“VC++ 目录 --& 包含目录”中添加上 &openssl_home&\include(不是 &openssl_home&\include\openssl,因为 stdsoap2.h 文件包含头文件的时候已经将 openssl 子目录考虑进去了)再将 &openssl_home&\bin 目录下 libeay32.dll 和 libeay32.dll 拷贝到将生成可执行文件的路径下。注意! 上述的步骤完毕后,编译并运行,可能会有如
所示的错误图 9. URL 不正确引发的错误引发这个问题的原因是生成的 soapClient.cpp 文件中定义的用于调用 web 服务的函数里,默认的 URL 开头多了一个空格,如
所示:图 10. URL 开头多了个空格解决的方法,要么手动删除这个空格,要么在
中直接把 &service_https& 以字符串形式作为调用 web 服务的函数(本文中为 soap_call___ns2__sayHello() 函数)的第二个参数传入。上述问题解决后,再次编译和运行就应该能够看到输出结果“Hello, the beautiful world!”Linux 平台下的编译和运行Linux 平台下以
的 C 代码为例。输入编译命令:gcc -o Hellos -DWITH_OPENSSL -lcrypto -lssl
*.c即可生成可执行文件。这里同样要注意
所说到的 URL 头部多了一个空格的问题。编译和运行没有其它问题的话,就应该能够看到输出结果“Hello, the beautiful world!”基于证书认证的 web 服务前面描述了搭建支持 https 的 web 服务及访问的方法,但是客户端和服务端之间的通信并没有涉及到证书的认证,接下来我们将要描述如何进行基于证书认证的通信。关于 soap_ssl_client_context() 函数在
中,我们都使用到了 soap_ssl_client_context() 函数,这个函数的定义位于 stdsoap2.cpp 或 stdsoap2.c 中,函数原型为:int SOAP_FMAC2 soap_ssl_client_context(struct soap *soap,unsigned short flags,const char *keyfile,const char *password,const char *cafile,const char *capath,const char *randfile)在 gSOAP 网站的 User Guide 页面可以找到若干处对该函数各个入参注释的片段,大致的含义如下:struct soap *soap ——用于 soap 通信的结构指针unsigned short flags ——是否进行证书认证的标志const char *keyfile ——如果服务端要认证客户端,填写客户端的“证书 +key”拼接文件名const char *password ——如果服务端要认证客户端,填写客户端的 key 文件的密码const char *cafile ——如果客户端要认证服务端,填写 CA 证书文件名(要包含路径)const char *capath ——如果客户端要认证服务端,填写 CA 路径或 NULL(本文都用 NULL)const char *randfile ——如果认证过程需要随机文件,填写随机文件名,否则填写 NULL其中第二个表示认证标志的参数,常用的宏定义位于 stdsoap2.h 中,如
所示:图 11. gSOAP 证书认证宏定义之前我们用的 SOAP_SSL_NO_AUTHENTICATION 只是供测试使用,不会进行证书的认证,下文中我们将使用 SOAP_SSL_DEFAULT 参数。客户端验证服务端证书服务端 tomcat7 保持
所述的配置不变。简单的修改 soap_ssl_client_context() 中的参数即可,修改后的代码片段,如
所示,其中,ca.crt 文件就是前文所述的 CA 根证书。清单 6. 客户端验证服务端证书代码
if(soap_ssl_client_context(&tClientSoap, SOAP_SSL_DEFAULT,
NULL, NULL, "D:\\certs\\ca.crt", NULL, NULL))
soap_print_fault(&tClientSoap, stderr);
return -1;
}注意!前文曾说过,如果服务端证书详细信息中的 CommonName(名字与姓氏)与客户端访问的 URL 的域名或 IP 地址不一致(例如,证书中填写的是“localhost”,客户端访问时使用的 &service_https& 中是“127.0.0.1”),会导致访问失败。具体报错的代码片段,可以在 stdsoap2.cpp 或 stdsoap2.c 中的 tcp_connect() 函数里找到,如
所示:图 12. 证书信息与 URL 不一致的检查由于
所示的错误提示并不打印在标准输出(通常是屏幕)上,所以一旦出错,客户端程序最多在具体调用 web 服务的函数(本文中为 soap_call___ns2__sayHello() 函数)处返回错误码为 30 的打印(SOAP_SSL_ERROR),难以直接看出原因,所以要特别注意。编译方法同前文。如果没什么问题,运行应该能够看到输出结果“Hello, the beautiful world!”服务端验证客户端证书服务端 tomcat 的配置文件需要在
的配置基础上修改,修改后的配置片段见 :图 13. 服务端验证客户端证书的配置这里我们加上了 truststoreFile 和 truststorePass 字段,并把 clientAuth 的值改为了 true。修改后记得重启 tomcat7 服务。注意! 本例中 trustoreFile 和 keystoreFile 配置成同一个 keystore 文件了,这是因为 keystore 可以根据别名(alias)存放多份密钥与证书。完全可以将 CA 证书导入另一个单独的 keystore 文件里,作为 truststoreFile 的参数。客户端的代码需要在
的基础上继续修改,见 。这里,假定 client.pem 文件中包含的 key 文件的保护口令是“client”。清单 7. 服务端验证客户端证书代码
if(soap_ssl_client_context(&tClientSoap, SOAP_SSL_DEFAULT,
"D:\\certs\\client.pem", "client",
"D:\\certs\\ca.crt", NULL, NULL))
soap_print_fault(&tClientSoap, stderr);
return -1;
}编译方法同前文。如果没什么问题,运行应该能够看到输出结果“Hello, the beautiful world!”
相关主题 在 ,您将找到有关 Web 服务和 SOA 的文章、教程、标准和其他技术资源。
gSOAP 网站提供了 openssl 网站提供了 从 tomcat 网站下载 的 tomcat 工具从 axis2 网站下载 下载
的压缩包下载
工具的压缩包安装和编译 openssl 的时候,如果缺少 perl 工具,可以从
添加或订阅评论,请先或。
有新评论时提醒我
static.content.url=/developerworks/js/artrating/SITE_ID=10Zone=SOA and web servicesArticleID=833399ArticleTitle=通过双向证书认证使用 gSOAP 访问 web servicespublish-date=}

我要回帖

更多关于 域名空间解析怎么弄 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信