该项目中.Net主要作为客户端,去调用java平台下的webservice,以下主要是针对一些技术和问题进行总结
一: 需要用.net的客户端去调用JAVA中CXF的WEBSERVICE .其中连接到服务端是通过HTTPS的方式 ,并且需要通过证书做签名验证。
在技术调研中 ,主要分为以下几个步骤逐步去实现 。
1 由于证书是在JAVA的服务端所提供,需要把JKS格式的证书转为.NET所能支持的PFX格式的证书。
2 加载证书到证书列表中
3 在CXF服务端关闭签名的情况下,.net通过HTTPS的方式能够和服务端进行通信。
4 在CXF服务端需要签名的情况下,.net通过证书签名和服务端进行互通信 。
5 在CXF服务端分别需要签名和加密的情况下,.net通过两个证书分别进行签名和加密、解密和服务端进行通信。
步骤一得解决 :
通过网上下载的工具jks2pfx 转换为pfx格式的证书。具体转换的方法 可 查询相关的资料。
步骤二
打开浏览器---->Internet 选项----->内容----->证书----->个人,默认是保存到当前用户CurrentUser,你会看到刚才制作的证书。这个可以查看部分证书,但是功能有限。我们还是使用控制台证书管理工具
导入证书到信任的人和信任的CA机构里。步骤如下:
1.导出证书文件,带密钥的pfx文件。使用mmc,保存到桌面位置(方便查找)。这里记住你制作证书的密码。要使用。
2.导入证书到信任的人。使用任务-导入向导--选择证书文件,导入即可。
3.导入证书到信任的机构,使用任务-导入向导--选择证书文件,导入即可。这个证书就被信任了
步骤三: 通过对方公布的地址,加载后生成相应的代理类 ,以下是主要关键的代码实现。
public static bool myCertificateValidation(Object sender, X509Certificate cert, X509Chain chain, SslPolicyErrors Errors)
{ return true; }
ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(myCertificateValidation);
//以上的代码为 验证服务器证书回调自动验证
EndpointAddress ea = new EndpointAddress(" https://10.101.16.114:8090/cxf "); //服务节点的地址
BasicHttpBinding myBinding = new BasicHttpBinding(); //因为JAVA 服务端用的SOAP格式为1.1不是1.2,所以不能够用WCF中对安全支持比较好的WSHttpBinding的绑定。WSHttpBinding只支持SOAP 1.2 .
myBinding.Security.Mode = BasicHttpSecurityMode.Transport; //安全模式为通道
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate; //证书验证方式
//生成代理类
ManageNumberInterfacePortTypeClient wcfServiceProxyHttp = new ManageNumberInterfacePortTypeClient(myBinding,ea);
//加载服务端分给客户端的证书
wcfServiceProxyHttp.ClientCredentials.ClientCertificate.SetCertificate(
StoreLocation.CurrentUser, //证书存储位置 当前用户
StoreName.My,//存储目录
X509FindType.FindBySubjectName,"cp2"); //证书的主题名称
。。。。。调用服务的方法
步骤四 :
以下只列出与步骤三不同或新增的代码
BasicHttpBinding myBinding = new BasicHttpBinding();
myBinding.Security.Mode = BasicHttpSecurityMode.TransportWithMessageCredential; //安全模式为通道加消息的验证方式
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Certificate;
myBinding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate; //传递的消息也需要安全验证
BindingElementCollection elements = myBinding.CreateBindingElements();
//因为CXF服务端返回的消息 没有消息的安全头,所以要设置为接受不安全的响应消息。.net默认的情况是只能接受安全的消息
// 即在request消息中有安全头,返回的消息中必须有安全头
//默认是没有EnableUnsecuredResponse的属性,需要安装补丁NDP30SP2-KB971493-x86.exe 才能够设置此属性
elements.Find<TransportSecurityBindingElement>().EnableUnsecuredResponse = true;
// wcf的绑定方式设置为自定义的绑定方式
CustomBinding cusBinding = new CustomBinding(elements);
ManageNumberInterfacePortTypeClient wcfServiceProxyHttp = new ManageNumberInterfacePortTypeClient(cusBinding,ea);
步骤五:
目前在java服务端加密和解密过程中 ,不管是.net和客户端 还是java的服务端 总不能够解密对方发送过来的消息 。但是 如果是在同一个平台下
不管是.NET的WCF 还是java 的cxf ,同样的程序加密和解密总是没有问题的 .该步骤的实现有待解决 。
以上情况只是针对.net客户端去调用JAVA CXF服务端这种跨平台的特殊情况 。如果在同一个平台下 ,实现起来应该简单的多。
二 关于Enunciate自动生成.Net客户端代码的问题,以及如何手工解决。
Enunciate是java平台下的开源工具,主要功能是可以针对java的各种webservice服务,自动的生成各个平台下(包括java,.net,c)客户端调用代码或组件
以下主要是针对自动生成.Net客户端代码的测试和问题总结。
生成的代码包中,主要有三个文件
后缀为dll的文件,可以在项目中直接引用。
后缀为cs的文件,其实是后缀为dll的文件的源码,在项目中也可以直接引用该文件
后缀为xml,针对后缀为dll的文件中的类和方法的说明。
在测试工程代码中,首先需要引用dll的文件或者生成的cs文件。
示例代码如下
CallDivertProcessService callDiverService = new CallDivertProcessService();
// Test "Apply" methord
Com.Bt.Calldivert.CallDivert callDivert = new Com.Bt.Calldivert.CallDivert();
callDivert.Source = "123456789";
callDivert.DivertType = "1";
CallDivertTxResponse callDivertTxResponse = callDiverService.Apply(callDivert);
Console.WriteLine(callDivertTxResponse.TxId.ToString());
但是在以上的代码中, 总是会抛出异常,程序运行失败。
经过对异常分析后,手工改动了 Enunciate生成的cs文件。程序运行正常。具体源码和修改前后的工程对比,可以参考附件EnunciateTest.rar
该压缩包中有三个工程。
1 ImportDll 直接引用Enunciate自动生成后的dll文件,工程运行失败。
2 ImportCsFile 直接引用Enunciate自动生成后的cs文件,工程运行失败。
3 CsFileManualChanged 手工修改Enunciate自动生成的cs文件的一些地方,工程运行成功。
通过对比,在每个生成的客户端方法中,默认情况下方法的输入参数和输出参数对应序列化后XML的命名空间都为空 即:Namespace="",这就造成了对XML验证失败,产生异常。
修改之后,可以把Namespace=""替换成Form = System.Xml.Schema.XmlSchemaForm.Unqualified ,就是说不需要在验证XML的时候,验证它的命名空间。
修改之后,程序可以正常运行。
主要参考了 http://www.cnblogs.com/frank_xl/tag/WCF%E5%88%86%E5%B8%83%E5%BC%8F%E5%AE%89%E5%85%A8%E5%BC%80%E5%8F%91%E5%AE%9E%E8%B7%B5/