[WCF安全系列]實(shí)例演示:TLS/SSL在WCF中的應(yīng)用[HTTPS]
上一篇演示的是綁定類(lèi)型為NetTcpBinding情況下基于TLS/SSL的Transport安全模式的實(shí)現(xiàn),接下來(lái)我們改用另外一種綁定:WS2007HttpBinding。對(duì)于基于HTTP的綁定,Transport安全模式的實(shí)現(xiàn)方式又根據(jù)寄宿方式的不同而具有一定的差異,我們首先來(lái)介紹自我寄宿的方式。
一、自我寄宿(Self-Hosting)
無(wú)論對(duì)于HTTPS還是SSL Via TCP,服務(wù)端都需要綁定一個(gè)證書(shū)。對(duì)于采用后者的NetTcpBinding,我們是通過(guò)ServiceCredentials這個(gè)服務(wù)行為來(lái)進(jìn)行證書(shū)設(shè)置的。但是對(duì)于HTTPS,我們需要通過(guò)相應(yīng)的命令行工具將一個(gè)X.509證書(shū)綁定到相應(yīng)的端口。而這個(gè)工具的選擇依賴(lài)于機(jī)器的操作系統(tǒng),對(duì)于Windows XP和Windows 2003,該命令行工具為httpcfg.exe,而對(duì)應(yīng)之后的版本,則是netsh.exe。關(guān)于如何通過(guò)httpcfg.exe和netsh.exe為端口設(shè)置SSL證書(shū),你可以參考:http://msdn.microsoft.com/zh-cn/library/ms733791.aspx。
httpcfg.exe和netsh.exe均是通過(guò)證書(shū)的指紋(thumbprint)來(lái)關(guān)聯(lián)具體的證書(shū)的,在這里具有全局唯一特性的指紋可以看成是證書(shū)的唯一標(biāo)識(shí)。我們之前已經(jīng)通過(guò)MakeCert命令行創(chuàng)建了一個(gè)主題為Jinnan-PC的證書(shū),我們現(xiàn)在重用該證書(shū)。你可以通過(guò)MMC的證書(shū)管理單元來(lái)查看證書(shū)的指紋,并將其拷貝到寫(xiě)字板上(比如指紋為:?f332bf17db3abb8f9a9a2694ba2c75da701bef0f),然后根據(jù)操作系統(tǒng)的不同分別執(zhí)行httpcfg.exe和netsh.exe命令行,為端口3721進(jìn)行SSL證書(shū)的設(shè)置,你可以將任意有效的GUID作為appid的參數(shù)。
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}
接下來(lái)我們將服務(wù)寄宿配置替換成如下的形式。從配置中我們可以看出,寄宿服務(wù)的唯一終結(jié)點(diǎn)采用了被設(shè)置成Transport模式,客戶(hù)端憑證類(lèi)型為None的WS2007HttpBinding。地址被設(shè)置成https://Jinan-PC:3721/calculatorservice,3721正式上面我們進(jìn)行SSL證書(shū)設(shè)置的端口。
<?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>
客戶(hù)端的配置和編程同樣進(jìn)行相應(yīng)的修改,具有與服務(wù)端相同的綁定設(shè)置。具體的配置和服務(wù)調(diào)用程序如下所示。
<?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>
服務(wù)調(diào)用程序:
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)); ;
}
然后我們運(yùn)行程序,你會(huì)發(fā)現(xiàn)如下圖所示的SecurityNegotiationException異常在服務(wù)調(diào)用過(guò)程中被拋出,并提示“無(wú)法為SSL/TLS 安全通道與頒發(fā)機(jī)構(gòu)“jinnan-pc:3721”建立信任關(guān)系”。拋出異常的原因和之前一致:證書(shū)不受信任,因?yàn)镠TTPS在默認(rèn)的情況下依然采用ChainTrust認(rèn)證模式。
如果證書(shū)是官方機(jī)構(gòu)頒發(fā),你可以將CA證書(shū)導(dǎo)入到“受信任根證書(shū)頒發(fā)機(jī)構(gòu)”存儲(chǔ)區(qū)來(lái)解決這個(gè)問(wèn)題。但是由于對(duì)于我們這個(gè)測(cè)試程序來(lái)說(shuō),你需要需求另外的辦法,也就是改變客戶(hù)端對(duì)SSL證書(shū)的認(rèn)證方式。不過(guò)這與采用NetTcpBinding時(shí)通過(guò)終結(jié)點(diǎn)行為ClientCredentials來(lái)設(shè)置服務(wù)證書(shū)認(rèn)證模式的方式有所不同,這里需要采用另外一種方式。你需要通過(guò)注冊(cè)ServicePointManager靜態(tài)ServerCertificateValidationCallback回調(diào)自定義證書(shū)認(rèn)證方式,ServerCertificateValidationCallback回調(diào)在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);
在下面給出的代碼片斷中,我通過(guò)在進(jìn)行服務(wù)調(diào)用之前通過(guò)注冊(cè)ServerCertificateValidationCallback回調(diào)的方式來(lái)忽略掉對(duì)SSL證書(shū)的認(rèn)證,就可以抑制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: }
對(duì)于SSL證書(shū)的認(rèn)證,還有一點(diǎn)需要說(shuō)明的是:在默認(rèn)的情況下,客戶(hù)端除了采用ChainTrust模式對(duì)證書(shū)進(jìn)行認(rèn)證之外,還具有一個(gè)認(rèn)證規(guī)則,那就是要求終結(jié)點(diǎn)地址的DNS和證書(shū)的主體名稱(chēng)相匹配。以我們創(chuàng)建的這個(gè)程序?yàn)槔绻覀儗⒖蛻?hù)端配置文件中的終結(jié)點(diǎn)地址從https://Jinnan-PC:3721/calculatorservice替換成https://localhost:3721/calculatorservice,在進(jìn)行服務(wù)調(diào)用的時(shí)候會(huì)拋出SecurityNegotiationException異常。
二、IIS寄宿
最后我們來(lái)演示IIS寄宿方式。如果你的IIS中沒(méi)有一個(gè)SSL站點(diǎn),你需要手工創(chuàng)建。所有先來(lái)演示一樣如何在你的IIS中創(chuàng)建一個(gè)SSL站點(diǎn),這里以IIS 7.5為例。
當(dāng)你開(kāi)啟了IIS管理器之后,點(diǎn)擊左側(cè)邊欄的“應(yīng)用程序池(Application Pool)”結(jié)點(diǎn),打開(kāi)應(yīng)用程序池列表界面。然后通過(guò)右擊彈出上下文菜單,并選擇“添加應(yīng)用程序池(Add Application Pool)”菜單項(xiàng),打開(kāi)添加應(yīng)用程序池對(duì)話(huà)框。設(shè)置添加的應(yīng)用程序池的名稱(chēng)(比如“DefaultSSLAppPool”),選擇.NET版本(.NET Framework 4.0.30319)和托管管道模式(Integrated)。點(diǎn)擊確認(rèn)后,新的應(yīng)用程序池被創(chuàng)建出來(lái)。
接下來(lái)我們需要?jiǎng)?chuàng)建使用這個(gè)應(yīng)用程序池的SSL站點(diǎn)。右擊“站點(diǎn)(Sites)”結(jié)點(diǎn),選擇“添加Web站點(diǎn)(Add Web Site)”菜單項(xiàng),進(jìn)入添加Web站點(diǎn)對(duì)話(huà)框。在該對(duì)話(huà)框中設(shè)置新建站點(diǎn)的名稱(chēng)(Default SSL Web Site),選擇剛剛創(chuàng)建的應(yīng)用程序池(DefaultSSLAppPool),并為站點(diǎn)設(shè)置一個(gè)本地的物理路徑。在綁定類(lèi)型列表中選擇https,保持IP地址和端口的默認(rèn)值。在SSL證書(shū)下拉框中你會(huì)看到我們之前創(chuàng)建的證書(shū)(Jinnan-PC),選擇它作為站點(diǎn)的SSL證書(shū)。點(diǎn)擊確認(rèn)按鈕后,新的站點(diǎn)被創(chuàng)建出來(lái)。
SSL站點(diǎn)被成功創(chuàng)建之后,你需要在該站點(diǎn)中創(chuàng)建一個(gè)應(yīng)用程序,起名為WcfServices,并將物理地址影射為解決方案中Services項(xiàng)目的根目錄。然后你需要對(duì)Services項(xiàng)目的“生成(Build)”進(jìn)行相應(yīng)的設(shè)置,將編譯后的目標(biāo)目錄從默認(rèn)的“\bin\debug”改成“\bin”,以確保項(xiàng)目編譯后的程序集被生成到bin目錄下。
IIS寄宿需要為服務(wù)創(chuàng)建相應(yīng)的.svc文件,此時(shí)你直接在Services項(xiàng)目中添加一個(gè)文本文件,起名為CalculatorService.svc,并為其添加如下的內(nèi)容。
1: <%@ ServiceHost Service="Artech.WcfServices.Services.CalculatorService" %>
在這之后,同樣在Services項(xiàng)目中添加一個(gè)Web.config文件,定義如下一段服務(wù)寄宿的配置。在這段配置中,除了無(wú)需指定終結(jié)點(diǎn)地址之外,其他所有的配置與通過(guò)自我寄宿方式別無(wú)二致。
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>
至此服務(wù)寄宿方面的工作已經(jīng)完畢,你只需要在Client項(xiàng)目中的配置中修改一下終結(jié)點(diǎn)地址(https://Jinnan-PC/WcfServices/CalculatorService.svc)就能直接執(zhí)行你的程序。


上一篇演示的是綁定類(lèi)型為NetTcpBinding情況下基于TLS/SSL的Transport安全模式的實(shí)現(xiàn),接下來(lái)我們改用另外一種綁定:WS2007HttpBinding。對(duì)于基于HTTP的綁定,Transport安全模式的實(shí)現(xiàn)方式又根據(jù)寄宿方式的不同而具有一定的差異

浙公網(wǎng)安備 33010602011771號(hào)