[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”建立信任關係”。拋出異常的原因和之前一致:。
如果證書是官方機構頒發,你可以將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