閱讀757 返回首頁    go 阿裏雲 go 技術社區[雲棲]


[WCF安全係列]實例演示:TLS/SSL在WCF中的應用[HTTPS]

上一篇演示的是綁定類型為NetTcpBinding情況下基於TLS/SSL的Transport安全模式的實現,接下來我們改用另外一種綁定:WS2007HttpBinding。對於基於HTTP的綁定,Transport安全模式的實現方式又根據寄宿方式的不同而具有一定的差異,我們首先來介紹自我寄宿的方式。

無論對於HTTPS還是SSL Via TCP,服務端都需要綁定一個證書。對於采用後者的NetTcpBinding,我們是通過ServiceCredentials這個服務行為來進行證書設置的。但是對於HTTPS,我們需要通過相應的命令行工具將一個X.509證書綁定到相應的端口。而這個工具的選擇依賴於機器的操作係統,對於Windows XP和Windows 2003,該命令行工具為,而對應之後的版本,則是。關於如何通過httpcfg.exe和netsh.exe為端口設置SSL證書,你可以參考:https://msdn.microsoft.com/zh-cn/library/ms733791.aspx

httpcfg.exe和netsh.exe均是通過證書的來關聯具體的證書的,在這裏具有全局唯一特性的指紋可以看成是證書的唯一標識。我們之前已經通過MakeCert命令行創建了一個主題為Jinnan-PC的證書,我們現在重用該證書。你可以通過MMC的證書管理單元來查看證書的指紋,並將其拷貝到寫字板上(比如指紋為:‎f332bf17db3abb8f9a9a2694ba2c75da701bef0f),然後根據操作係統的不同分別執行httpcfg.exe和netsh.exe命令行,為端口3721進行SSL證書的設置,你可以將任意有效的GUID作為appid的參數。

httpcfg set ssl -i 0.0.0.0:3721 -h f332bf17db3abb8f9a9a2694ba2c75da701bef0f
OR
netsh http add sslcert ipport=0.0.0.0:3721 certhash= f332bf17db3abb8f9a9a2694ba2c75da701bef0f
  appid={CFA5621F-CD55-4009-AD7E-51EDDAEC5786}

接下來我們將服務寄宿配置替換成如下的形式。從配置中我們可以看出,寄宿服務的唯一終結點采用了被設置成Transport模式,客戶端憑證類型為None的WS2007HttpBinding。地址被設置成https://Jinan-PC:3721/calculatorservice,3721正式上麵我們進行SSL證書設置的端口。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
  <bindings>
    <ws2007HttpBinding>
      <binding name="transportWS2007HttpBinding">
        <security mode="Transport">
          <transport clientCredentialType="None"/>
        </security>
      </binding>
    </ws2007HttpBinding>      
  </bindings>
  <services>
    <service name="Artech.WcfServices.Services.CalculatorService">
      <endpoint address="https://Jinnan-PC:3721/calculatorservice" binding="ws2007HttpBinding" bindingConfiguration="transportWS2007HttpBinding" 
contract="Artech.WcfServices.Contracts.ICalculator" />
    </service>
  </services>
  </system.serviceModel>
</configuration>

客戶端的配置和編程同樣進行相應的修改,具有與服務端相同的綁定設置。具體的配置和服務調用程序如下所示。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <bindings>
      <ws2007HttpBinding>
        <binding name="transportWS2007HttpBinding">
          <security mode="Transport">
            <transport clientCredentialType="None"/>
          </security>
        </binding>
      </ws2007HttpBinding>
    </bindings>
    <client>
      <endpoint name="calculatorService" address="https://Jinnan-PC:3721/calculatorservice" binding="ws2007HttpBinding" 
bindingConfiguration="transportWS2007HttpBinding" contract="Artech.WcfServices.Contracts.ICalculator" />
    </client>
  </system.serviceModel>
</configuration>

服務調用程序:

using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
{
    ICalculator calculator = channelFactory.CreateChannel();
    Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2)); ;
}

然後我們運行程序,你會發現如下圖所示的SecurityNegotiationException異常在服務調用過程中被拋出,並提示“無法為SSL/TLS 安全通道與頒發機構“jinnan-pc:3721”建立信任關係”。拋出異常的原因和之前一致:。

image

如果證書是官方機構頒發,你可以將CA證書導入到“受信任根證書頒發機構”存儲區來解決這個問題。但是由於對於我們這個測試程序來說,你需要需求另外的辦法,也就是改變客戶端對SSL證書的認證方式。不過這與采用NetTcpBinding時通過終結點行為ClientCredentials來設置服務證書認證模式的方式有所不同,這裏需要采用另外一種方式。你需要通過注冊ServicePointManager靜態ServerCertificateValidationCallback回調自定義證書認證方式,ServerCertificateValidationCallback回調在ServicePointManager中的定義如下麵的代碼片斷所示。

   1: public class ServicePointManager
   2: {
   3:     //其他成員
   4:     public static RemoteCertificateValidationCallback ServerCertificateValidationCallback { get; set; }
   5: }
   6: public delegate bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, 
   7: X509Chain chain, SslPolicyErrors sslPolicyErrors);

在下麵給出的代碼片斷中,我通過在進行服務調用之前通過注冊ServerCertificateValidationCallback回調的方式來忽略掉對SSL證書的認證,就可以抑製SecurityNegotiationException異常的拋出。

   1: ServicePointManager.ServerCertificateValidationCallback+=( sender,  certificate,  chain,  sslPolicyErrors)=>true;
   2: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
   3: {
   4:     ICalculator calculator = channelFactory.CreateChannel();
   5:     Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 1, 2, calculator.Add(1, 2)); ;
   6: }

對於SSL證書的認證,還有一點需要說明的是:在默認的情況下,客戶端除了采用ChainTrust模式對證書進行認證之外,還具有一個認證規則,那就是要求。以我們創建的這個程序為例,如果我們將客戶端配置文件中的終結點地址從https://Jinnan-PC:3721/calculatorservice替換成https://localhost:3721/calculatorservice,在進行服務調用的時候會拋出SecurityNegotiationException異常。

最後我們來演示IIS寄宿方式。如果你的IIS中沒有一個SSL站點,你需要手工創建。所有先來演示一樣如何在你的IIS中創建一個SSL站點,這裏以IIS 7.5為例。

當你開啟了IIS管理器之後,點擊左側邊欄的“應用程序池(Application Pool)”結點,打開應用程序池列表界麵。然後通過右擊彈出上下文菜單,並選擇“添加應用程序池(Add Application Pool)”菜單項,打開添加應用程序池對話框。設置添加的應用程序池的名稱(比如“DefaultSSLAppPool”),選擇.NET版本(.NET Framework 4.0.30319)和托管管道模式(Integrated)。點擊確認後,新的應用程序池被創建出來。

接下來我們需要創建使用這個應用程序池的SSL站點。右擊“站點(Sites)”結點,選擇“添加Web站點(Add Web Site)”菜單項,進入添加Web站點對話框。在該對話框中設置新建站點的名稱(Default SSL Web Site),選擇剛剛創建的應用程序池(DefaultSSLAppPool),並為站點設置一個本地的物理路徑。在綁定類型列表中選擇https,保持IP地址和端口的默認值。在SSL證書下拉框中你會看到我們之前創建的證書(Jinnan-PC),選擇它作為站點的SSL證書。點擊確認按鈕後,新的站點被創建出來。

SSL站點被成功創建之後,你需要在該站點中創建一個應用程序,起名為WcfServices,並將物理地址影射為解決方案中Services項目的根目錄。然後你需要對Services項目的“生成(Build)”進行相應的設置,將編譯後的目標目錄從默認的“\bin\debug”改成“\bin”,以確保項目編譯後的程序集被生成到bin目錄下。

IIS寄宿需要為服務創建相應的.svc文件,此時你直接在Services項目中添加一個文本文件,起名為CalculatorService.svc,並為其添加如下的內容。

   1: <%@ ServiceHost Service="Artech.WcfServices.Services.CalculatorService" %>

在這之後,同樣在Services項目中添加一個Web.config文件,定義如下一段服務寄宿的配置。在這段配置中,除了無需指定終結點地址之外,其他所有的配置與通過自我寄宿方式別無二致。

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <configuration>
   3:   <system.serviceModel>
   4:     <bindings>
   5:       <ws2007HttpBinding>
   6:         <binding name="transportWS2007HttpBinding">
   7:           <security mode="Transport">
   8:             <transport clientCredentialType="None"/>
   9:           </security>
  10:         </binding>
  11:       </ws2007HttpBinding>
  12:     </bindings>
  13:     <services>
  14:       <service name="Artech.WcfServices.Services.CalculatorService">
  15:         <endpoint binding="ws2007HttpBinding" bindingConfiguration="transportWS2007HttpBinding" 
  16: contract="Artech.WcfServices.Contracts.ICalculator" />
  17:       </service>
  18:     </services>
  19:   </system.serviceModel>
  20: </configuration>

至此服務寄宿方麵的工作已經完畢,你隻需要在Client項目中的配置中修改一下終結點地址(https://Jinnan-PC/WcfServices/CalculatorService.svc)就能直接執行你的程序。


作者:蔣金楠
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
原文鏈接

最後更新:2017-10-26 16:34:40

  上一篇:go  [WCF安全係列]實例演示:TLS/SSL在WCF中的應用[SSL over TCP]
  下一篇:go  [WCF安全係列]服務憑證(Service Credential)與服務身份(Service Identity)