原文:http://www.xuebuyuan.com/641669.html

到现在为止,我们AEP平台已经发布很长一段时间了,也有很多ISV接入并上线了,就语言而言,目前主要有三类:Java、.Net、Php;Java和Php的调用不存在很复杂的问题,但是.Net就要相对复杂不少, 现在已上线的ISV采用的是.Net SDK 2.0 + WSE 2.0【Web Services Enhancements】,但是随着.Net 3.0和3.5的普及,我们需要支持更多的.Net接入方案;

总的来说,针对不同的.Net SDK版本有三种实现来满足对带有WS-Security支持的Web Service调用,即WSE 2.0、WSE 3.0、WCF【Windows Communication Foundation】;其中WSE 2.0针对的是VS 2003版本,WSE 3.0针对的是VS 2005版本,WCF针对的是VS 2008,从SDK要求来看,WSE 2.0和3.0是2.0,而WCF要求是3.0或3.5;前面我的同事已经将WSE 2.0调通,但是对WSE 3.0始终无法调通,具体可以参见《Web Service 、WS-Security、Java和.net的互通(在路上-基于SCA规范的应用服务框架成长记之四》;而WCF经过微软研究院几个月的调试,也已经调通,具体可以参见《.Net在Alibaba的AEP平台上的应用》;不幸的是,针对这两种配置方案经测试是不兼容的,因为不止是.Net客户端调整配置和代码,Java服务端仍然要做出调整,这对于我们的系统侵入是非常大的,因为现在已经有ISV采用WSE 2.0实现在生产环境运行了,要想在服务端做出调整的话必须要做到无缝升级,也即线上所有的ISV客户端无需做任何修改,否则这个升级代价会非常高;

功夫不负有心人啊,经过几天的研究,终于让我找到一个更加有效的解决方案,在新的配置方案下,WSE 2.0、WSE 3.0、WCF全部都可以调试通过,并且对Java端没有任何影响,Php的调用经确认也不存在任何问题;服务端OutflowSecurity配置文件修改如下:其中,1)items中添加了Timestamp的配置,并且在Signature之前,这是为了满足WCF的测试而特意设置的,幸好这不影响其他方案的调试;
2)signatureKeyIdentifier设置为DirectReference,该配置项在前面已经提到过,他和X509KeyIdentifier一样,是将签名者的证书公共部分直接通过soap xml传递给客户端,然后客户端再和他本地的公钥证书做对比,通过之后进行签名验证;关于该配置项,在Java服务端WSS4J的javadoc中描述有误,javadoc中说该项只允许两个值:IssuerSerial和SKIKeyIdentifier,但实际上他可以取5种值,这可能是导致很多人无法在.Net环境调试通过的原因;
3)signatureParts种指定了参与签名的是Timestamp和body部分,这也是WCF所特别需要的,因为WCF要求soap xml种的header部分都要参与签名;

<items>Timestamp Signature</items>
<signatureKeyIdentifier>DirectReference</signatureKeyIdentifier>
<signatureParts>{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{Element}{}Body</signatureParts>

注意,签名部分中Body的namespace是空的,而没有设置为http://schemas.xmlsoap.org/soap/envelope/(SOAP 1.1对应的ns)或者http://www.w3.org/2003/05/soap-envelope(对应SOAP 1.2),这是为了兼容SOAP 1.1和1.2两个版本,若指定了ns,则只能兼容其一,.Net、Java客户端调用默认都使用SOAP 1.1版,而WSF/PHP则默认使用1.2版本,这样就无法做到各语言的完全
服务端搞定之后,我们就可以来进行.Net客户端的调试工作了,这里就不描述证书的准备工作了,直接开始;注意:以下的配置方案是在带有WSS支持的Web Service服务端特定配置基础上调试通过的,随着服务端配置的变化,客户端的配置和编码也会有一定的调整,所以以下配置并不保证对所有服务端配置都联调成功;

WSE 2.0配置(VS 2003)

1)右键单击工程,选择WSE Settings 2.0 ...开始设置,若在VS 2005环境种使用WSE 2.0,则菜单中没有该项,需要单独打开WSE的Configuration Tool进行设置;
2)在Settings Tool中General页中选中Enable this projects for Web Services Enhancements;
3)Policy页中选中Enable Policy,点击Add ...按钮新建Policy配置文件;
4)Add or Rename Endpoint URI窗口中保留默认值<DefaultEndpoint>,点击OK;
5)保持Next,到Message Settings窗口中对Request Message、Response Message都选择Require Signatures,因为我们只需要进行签名验证,而不需要加密;
6)Next到Client Certificate窗口中,选择客户端签名需要的私钥证书;
7)Trusted Server Certificate窗口中,选择验证服务端签名需要的公钥证书;
8)保存退出,会在工程中出现policyCache.config配置文件,打开;
9)找到response对应的Policy配置项中的wsp:MessagePredicate和wssp:MessageParts,删除其中多余的配置项,只保留wsp:Body();
10)添加Web Reference,然后修改Reference.cs文件中继承的父类,由System.Web.Services.Protocols.SoapHttpClientProtocol修改为Microsoft.Web.Services2.WebServicesClientProtocol;对于此点可能在vs2003环境下面是不需要的,我只在VS 2005环境下面测试过,VS 2005下面是必须的;
11)写ws调用类并运行;
和我们以前WSE 2.0的配置相比,主要变化在于现在不需要选中Use RFC2380选项了;

WSE 3.0配置(VS 2005)

和WSE 2.0配置一样,完全借助于Configuration Tool,注意以下点:
1)可以先配置Policy再添加Web Reference引用,这样产生的代理类会自动继承Microsoft.Web.Services3.WebServicesClientProtocol;
2)调用代码中需要自己设置要使用的policy名称;
3)Security页中X.509 Certificate Settings中的选项都保持默认值,除了Store Location;
4)新建Policy时Message Protection步骤中选择要注意顺序,顺序的不同会产生很不一样的效果,结果会导致接口调用步成功,最傻瓜的操作如下图所示:
这应该是.Net下面调用带有WSS支持的Web Service最傻瓜的操作了,全向导性配置,只需要三行代码即可调用WS;

WCF配置(VS 2008)

WCF的配置又复杂一些了,因为WCF整合了许多其他的东西,而不仅仅是一个支持WS-Security的工具,配置文件中各项的选择性也非常的大,取值范围非常的广,这样反而让开发人员在配置的时候感觉到盲目;WCF也有自己的配置工具WCF Service Configuration Editor,可以从“工具”菜单栏或者开始菜单中加载;这里就不帖具体每项的配置了,因为配置工具中没有向导;直接帖一个可用的配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <!-- If you wan to turn on logging, uncomment the "sources" section below, and set the correct log files in sharedListeners section. -->
    <system.diagnostics>
        <sharedListeners>
          <!-- TODO: Please fix the log file name here! -->
            <add initializeData="F:TempTracesapp_messages_aliclient.svclog"
                type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                name="ServiceModelMessageLoggingListener" traceOutputOptions="Timestamp">
                <filter type="" />
            </add>
          <!-- TODO: Please fix the log file name here! -->
            <add initializeData="F:TempTracesapp_tracelog_aliclient.svclog"
                type="System.Diagnostics.XmlWriterTraceListener, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
                name="ServiceModelTraceListener" traceOutputOptions="Timestamp">
                <filter type="" />
            </add>
        </sharedListeners>
    </system.diagnostics>
    <system.serviceModel>
      <!-- To turn on message logging, set these flags to "true" -->
        <diagnostics>
            <messageLogging logEntireMessage="false" logMalformedMessages="false"
                logMessagesAtTransportLevel="false" />
        </diagnostics>
        <bindings>
            <customBinding>
                <binding name="Soap11CustomBinding">
                    <textMessageEncoding messageVersion="Soap11" />
                    <security defaultAlgorithmSuite="Basic128" allowSerializedSigningTokenOnReply="true"
                        authenticationMode="MutualCertificate" requireDerivedKeys="false"
                        securityHeaderLayout="Lax" includeTimestamp="true" keyEntropyMode="CombinedEntropy"
                        messageProtectionOrder="SignBeforeEncrypt" messageSecurityVersion="WSSecurity10WSTrustFebruary2005WSSecureConversationFebruary2005WSSecurityPolicy11BasicSecurityProfile10"
                        requireSecurityContextCancellation="false">
                        <secureConversationBootstrap />
                    </security>
                    <httpTransport />
                </binding>
            </customBinding>
        </bindings>
      <behaviors>
        <endpointBehaviors>
          <behavior name="NewBehavior">
            <clientCredentials>
              <clientCertificate findValue="CN=5" storeLocation="CurrentUser"
                storeName="My" x509FindType="FindBySubjectDistinguishedName" />
              <serviceCertificate>
                <defaultCertificate findValue="CN=alisoft" storeLocation="CurrentUser"
                  storeName="My" x509FindType="FindBySubjectDistinguishedName" />
                <authentication customCertificateValidatorType="" certificateValidationMode="PeerOrChainTrust" />
              </serviceCertificate>
              <issuedToken cacheIssuedTokens="false" />
            </clientCredentials>
          </behavior>
        </endpointBehaviors>
      </behaviors>
        <client>
            <!--121.0.18.160-->
            <endpoint address="http://localhost:1688/webservice/AppConsumeService"
                behaviorConfiguration="NewBehavior" binding="customBinding"
                bindingConfiguration="Soap11CustomBinding" contract="ServiceReference1.AppConsumeServicePortType"
                name="Soap11CustomBindingPort">
                <identity>
                    <dns value="alisoft" />
                    <certificateReference x509FindType="FindBySubjectName" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

客户端调用代码为:

ServiceReference1.AppConsumeServicePortTypeClient c = new ServiceReference1.AppConsumeServicePortTypeClient("Soap11CustomBindingPort");
//设置保护级别为签名
c.Endpoint.Contract.ProtectionLevel = System.Net.Security.ProtectionLevel.Sign;
string bal = c.checkBalance("85", "afc376c9-d14b-4820-bc77-e22878fa8ce3", 11);
Console.WriteLine("bal is:" + bal);

至于WCF配置中的细项我也还没有深入探讨过,以上的配置都是基于微软亚洲研究院联调成功的配置之上的;

.Net调用Java端带有WS-Security支持的Web Service各方案实战【转】的更多相关文章

  1. .Net调用Java端带有WS-Security支持的Web Service【亲测通过】

    做了几年的开发,今天终于鼓起勇气开通了博客园.平时都是找各种大牛,看他们的分享博客的解决BUG.从今天起,我也开始分享我学习之路.还望大家多多支持! 最近收到一个采用Axis2实现的WebServic ...

  2. 【转】基于CXF Java 搭建Web Service (Restful Web Service与基于SOAP的Web Service混合方案)

    转载:http://www.cnblogs.com/windwithlife/archive/2013/03/03/2942157.html 一,选择一个合适的,Web开发环境: 我选择的是Eclip ...

  3. android NDK 实用学习(五)-c++端调用java接口

    1,阅读此文章前请阅读前面文章,以免阅读出现障碍: android NDK 实用学习(一)-获取java端类及其类变量 android NDK 实用学习(二)-java端对象成员赋值和获取对象成员值 ...

  4. NET调用Java之100-Continue的坑

    场景:这段时间开发的时候遇到了需要NET调用java的restful api的情况,java端用的服务器是tomcat,框架是spring boot,net调用java端的接口之后只要java端的接口 ...

  5. .Net调用Java的实现方法

    一. IKVM 1.1下载配置IKVM 1.1.1. 下载路径 http://www.ikvm.net/index.html 1.1.2. 设置路径 解压ikvm-0.42.0.3.zip,并将%IK ...

  6. AndroidJNI 调用JAVA(转)

    转自:http://www.cnblogs.com/likwo/archive/2012/05/21/2512400.html   1. JNIEnv对象    对于本地函数    JNIEXPORT ...

  7. C#开发和调用Web Service

    http://blog.csdn.net/h0322/article/details/4776819 1.1.Web Service基本概念 Web Service也叫XML Web Service ...

  8. ASP.NET调用Web Service

    1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求, ...

  9. C# 调用 Web Service

    Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术.是:通过SOAP ...

随机推荐

  1. chrome 关闭安全模式

    chrome.exe --disable-web-security --user-data-dir

  2. fedora修改主目录文件名为英文

           在gnome-terminal里面能够显示中文的,但是在文本终端里面中文都是不能显示的,是一个小小的正方形.因此可以只把主目录文件名换成英文的,方便文本终端命令输入,而其他的一些地方还是 ...

  3. 服务器负载、CPU性能判断

    说在前面: 在linux操作系统中,我们一般查看系统的cpu负载情况常用的命令可以是uptime,top,还有vmstat等这些个都是可以有的.每个工具所提供的信息各不相同, 我这里要讨论的仅说cpu ...

  4. ehcache实现页面整体缓存和页面局部缓存

    之前写过spring cache和ehcache的基本介绍和注解实现缓存管理,今天记录下web项目的页面缓存技术. 页面缓存是否有必要?. 这样说吧,几乎所有的网站的首页都是访问率最高的,而首页上的数 ...

  5. Tomcat java.lang.OutOfMemoryError: PermGen space error

    Often time, Tomcat may hits the following java.lang.OutOfMemoryError: PermGen space error. java.lang ...

  6. Activiti工作流引擎简介

    Activiti工作流引擎简介 一.概述 Activiti是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务流程管理,工作流,服务协作等领域的一个开源,灵活 ...

  7. 【转】为什么我的DIV块前总有空隙?

    在做网站项目时,博主爱吾所爱(爱生活=爱技术)很偶然地碰到一个奇怪的事情.我的DIV嵌套在另一个DIV里,总是出现这样一行空隙: Firebug查看内外两层DIV的margin, padding, l ...

  8. HTML深入探究(一)HTML入门

          HTML:超文本标记语言HyperText Markup Language,是一种用于创建网页的标准标记语言.HTML 不是一种编程语言,而是一种标记语言,标记语言是一套标记标签 (mar ...

  9. 【Docker】数据库动态授权组件在Kubernetes集群下的测试过程记录

    背景 我们都知道出于安全性考虑,生产环境的权限一般都是要做最小化控制,尤其是数据库的操作授权,更是重中之重. 博主所在公司使用的是Kubernetes(k8s)进行的集群容器管理,因为容器发布时的IP ...

  10. Mysql语句转义

    String sqlStr = "SELECT * FROM t_sys_dic WHERE idPath LIKE" + "'" + "/19/20 ...