.Net調用Java端帶有WS-Security支持的Web Service各方案實戰【轉】

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

到如今爲止,咱們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接入方案;java

總的來講,針對不一樣的.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客戶端無需作任何修改,不然這個升級代價會很是高;web

功夫不負有心人啊,通過幾天的研究,終於讓我找到一個更加有效的解決方案,在新的配置方案下,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部分都要參與簽名;
app

<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選項了;
ide

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>

客戶端調用代碼爲:ui

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配置中的細項我也尚未深刻探討過,以上的配置都是基於微軟亞洲研究院聯調成功的配置之上的;this

相關文章
相關標籤/搜索