[WCF安全系列]通過綁定元素看各種綁定對消息保護的實現
對消息進行簽名和加密分別解決了消息的一致性和機密性問題。而最終是僅僅采用簽名還是簽名與加密共用取決于契約中對消息保護級別的設置。但是具體的簽名和加密在整個WCF框架體系中如何實現?是采用對稱加密還是非對稱加密?密鑰如何而來?相信這些問題在本篇文章中你會找到答案。
目錄
一、BasicHttpBinding
二、WSHttpBinding、WS2007HttpBinding和WSDualHttpBinding
三、NetTcpBinding和NetNamedPipeBinding
四、NetMsmqBinding
五、總結
在本系列中我不斷在強調這么一個要點:整個安全傳輸的實施最終是在信道層實現的。而信道層是根絕終結點綁定創建的,而綁定從結構上是一系列綁定元素的有序集合。當綁定的安全開啟的時候,決定最終安全傳輸實現方式的必然是某一個或者多個綁定元素。了解相關綁定元素可以幫助讀者從本質上理解安全傳輸實現原理。
為了演示方便,我寫了如下一個針對Binding類型的擴展方法ListAllBindingElements,該方法會將綁定所有的綁定元素的類型打印出來。接下來,我們就利用這個擴展方法應用了那些常見的綁定,看看最終決定安全傳輸的是哪些綁定元素。
1: public static class BindingExtension
2: {
3: public static void ListAllBindingElements(this Binding binding)
4: {
5: int i = 0;
6: foreach (var bindingElement in binding.CreateBindingElements())
7: {
8: Console.WriteLine("\t{0}.{1}", ++i, bindingElement.GetType().FullName);
9: }
10: }
11: }
一、BasicHttpBinding
我們先來看看對于三種典型安全模式(Transport、Message和Mixed)下的BasicHttpBinding具體由哪些綁定元素構成,為了我編寫了如下的程序。
1: BasicHttpBinding binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
2: Console.WriteLine("Transport:");
3: binding.ListAllBindingElements();
4:
5: binding = new BasicHttpBinding(BasicHttpSecurityMode.Message);
6: binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
7: Console.WriteLine("Message:");
8: binding.ListAllBindingElements();
9:
10: binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
11: Console.WriteLine("Mixed:");
12: binding.ListAllBindingElements();
輸出結果:
1: Transport:
2: 1.System.ServiceModel.Channels.TextMessageEncodingBindingElement
3: 2.System.ServiceModel.Channels.HttpsTransportBindingElement
4: Message:
5: 1.System.ServiceModel.Channels.AsymmetricSecurityBindingElement
6: 2.System.ServiceModel.Channels.TextMessageEncodingBindingElement
7: 3.System.ServiceModel.Channels.HttpTransportBindingElement
8: Mixed:
9: 1.System.ServiceModel.Channels.TransportSecurityBindingElement
10: 2.System.ServiceModel.Channels.TextMessageEncodingBindingElement
11: 3.System.ServiceModel.Channels.HttpsTransportBindingElement
我們來具體分析一下最終在不同安全模式下輸出的綁定元素列表。對于Mixe安全模式下對服務的驗證、消息簽名和加密都是基于Transport安全,Message安全僅僅用于對客戶端的認證。所以對于Transport和Mixed模式,消息保護都是通過HttpsTransportBindingElement來實現。從名稱就可以看出來,這是一個基于HTTPS的傳輸綁定元素,這也再次印證了BasicHttpBinding通過HTTPS實現Transport安全模式的說法。
對于Message安全模式的三個綁定元素中,很明顯和安全傳輸相關的是AsymmetricSecurityBindingElement。從名稱我們就知道,該綁定元素通過非對稱加密的方式提供簽名和加密的實現。具體來說,對于請求消息來說,發送方使用自己的私鑰對消息進行簽名,使用接收方的公鑰對消息進行加密。接收方采用發送方的公鑰驗證簽名,用自己的私鑰對消息進行解密。這也是為什么在選擇了Message安全模式的情況下,基于用戶名/密碼的客戶端憑證不被支持的真正原因。
二、WSHttpBinding、WS2007HttpBinding和WSDualHttpBinding
我們按照相同的方式來分析基于WS的綁定,由于WSHttpBinding和WS2007HttpBinding僅僅在實現WS-*協議上面有所不同之外,整個設計基本相同。所以我們僅僅分析WS2007HttpBinding和WSDualHttpBinding。首先來分析WS2007HttpBinding,我們對前面的分析程序略加修改,將綁定類型替換成WS2007HttpBinding。
1: WS2007HttpBinding binding = new WS2007HttpBinding(SecurityMode.Transport);
2: Console.WriteLine("Transport:");
3: binding.ListAllBindingElements();
4:
5: binding = new WS2007HttpBinding(SecurityMode.Message);
6: Console.WriteLine("Message:");
7: binding.ListAllBindingElements();
8:
9: binding = new WS2007HttpBinding(SecurityMode.TransportWithMessageCredential);
10: Console.WriteLine("Mixed:");
11: binding.ListAllBindingElements();
輸出結果:
1: Transport:
2: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
3: 2.System.ServiceModel.Channels.TextMessageEncodingBindingElement
4: 3.System.ServiceModel.Channels.HttpsTransportBindingElement
5: Message:
6: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
7: 2.System.ServiceModel.Channels.SymmetricSecurityBindingElement
8: 3.System.ServiceModel.Channels.TextMessageEncodingBindingElement
9: 4.System.ServiceModel.Channels.HttpTransportBindingElement
10: Mixed:
11: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
12: 2.System.ServiceModel.Channels.TransportSecurityBindingElement
13: 3.System.ServiceModel.Channels.TextMessageEncodingBindingElement
14: 4.System.ServiceModel.Channels.HttpsTransportBindingElement
WS2007HttpBinding和BasicHttpBinding實現Transport安全都是基于HTTPS,所以在對于Transport和Mixed安全模式,HttpsTransportBindingElement實現了對消息的簽名和加密。而對于Message安全模式下包含的四個綁定元素,我們可以看出最終和安全傳輸相關的是一個叫做SymmetricSecurityBindingElement。從名稱我們都可以猜出,SymmetricSecurityBindingElement采用了對稱加密的實現了對消息的簽名和加密。這就意味著,客戶端和服務在進行正式的功能性消息交換之前,會相互協商生成一個僅限于雙方知道的密鑰。
接著來看用戶雙向通信的WSDualHttpBinding。通過前面的接收,我們已經知道了該邦綁定僅僅支持Message安全模式。我們同樣調用ListAllBindingElements擴展方法列出WSDualHttpBinding在Message安全模式下的所有綁定元素。
1: WSDualHttpBinding binding = new WSDualHttpBinding(WSDualHttpSecurityMode.Message);
2: Console.WriteLine("Message:");
3: binding.ListAllBindingElements();
輸出結果:
1: Message:
2: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
3: 2.System.ServiceModel.Channels.ReliableSessionBindingElement
4: 3.System.ServiceModel.Channels.SymmetricSecurityBindingElement
5: 4.System.ServiceModel.Channels.CompositeDuplexBindingElement
6: 5.System.ServiceModel.Channels.OneWayBindingElement
7: 6.System.ServiceModel.Channels.TextMessageEncodingBindingElement
8: 7.System.ServiceModel.Channels.HttpTransportBindingElement
從輸出結果我們可以看到,WSDualHttpBinding和WS2007HttpBinding(WSHttpBinding)在實現Message安全模式方面采用相同的機制,都是采用SymmetricSecurityBindingElement來實現的,最終進行簽名和加密的都是采用對稱加密的方式來實現。
三、NetTcpBinding和NetNamedPipeBinding
我們按照之前的方式來分析另外兩個只要應用于局域網環境中的兩個綁定,即NetTcpBinding和NetNamedPipeBinding。這兩個綁定和之前介紹的機遇HTTP/HTTPS傳輸協議的綁定有所不同。不論是BasicHttpBinding還是WSHttpBinding、WS2007HttpBinding和WSDualHttpBinding,當綁定的安全模式確定之后,綁定元素集合就確定了。但是對于NetTcpBinding和NetNamedPipeBinding來說,如果采用Transport安全模式,最終的綁定元素集合還和采用的認證方式有關。
下面是針對于NetTcpBinding的分析程序,對于Transport和Mixed安全模式,我們又分兩種情況:將客戶端憑證類型分別設置成Windows和Certificate。
1: NetTcpBinding binding = new NetTcpBinding(SecurityMode.Transport);
2: binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Windows;
3: Console.WriteLine("Transport(Windows):");
4: binding.ListAllBindingElements();
5:
6: binding = new NetTcpBinding(SecurityMode.Transport);
7: binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.Certificate;
8: Console.WriteLine("Transport(Certificate):");
9: binding.ListAllBindingElements();
10:
11: binding = new NetTcpBinding(SecurityMode.Message);
12: Console.WriteLine("Message:");
13: binding.ListAllBindingElements();
14:
15: binding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential);
16: binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
17: Console.WriteLine("Mixed(Windows):");
18: binding.ListAllBindingElements();
19:
20: binding = new NetTcpBinding(SecurityMode.TransportWithMessageCredential);
21: binding.Security.Message.ClientCredentialType = MessageCredentialType.Certificate;
22: Console.WriteLine("Mixed(Certificate):");
23: binding.ListAllBindingElements();
輸出結果:
1: Transport(Windows):
2: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
3: 2.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
4: 3.System.ServiceModel.Channels.WindowsStreamSecurityBindingElement
5: 4.System.ServiceModel.Channels.TcpTransportBindingElement
6: Transport(Certificate):
7: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
8: 2.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
9: 3.System.ServiceModel.Channels.SslStreamSecurityBindingElement
10: 4.System.ServiceModel.Channels.TcpTransportBindingElement
11: Message:
12: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
13: 2.System.ServiceModel.Channels.SymmetricSecurityBindingElement
14: 3.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
15: 4.System.ServiceModel.Channels.TcpTransportBindingElement
16: Mixed(Windows):
17: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
18: 2.System.ServiceModel.Channels.TransportSecurityBindingElement
19: 3.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
20: 4.System.ServiceModel.Channels.SslStreamSecurityBindingElement
21: 5.System.ServiceModel.Channels.TcpTransportBindingElement
22: Mixed(Certificate):
23: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
24: 2.System.ServiceModel.Channels.TransportSecurityBindingElement
25: 3.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
26: 4.System.ServiceModel.Channels.SslStreamSecurityBindingElement
27: 5.System.ServiceModel.Channels.TcpTransportBindingElement
從輸出結果我們看出這樣的問題:NetTcpBinding同樣采用SymmetricSecurityBindingElement實現Message模式安全。但是對于Transport安全模式的實現卻還決定于客戶端憑證類型(或者說認證方式)。在Windows認證下,WindowsStreamSecurityBindingElement用于使用Transport安全。而對于非Windows認證,對應的綁定元素變成了SslStreamSecurityBindingElement。對于實現NetTcpBinding基于Transport安全的兩個綁定元素WindowsStreamSecurityBindingElement和SslStreamSecurityBindingElement,它們具有相同的基類:StreamUpgradeBindingElement。
1: public abstract class StreamUpgradeBindingElement : BindingElement
2: {
3: //省略成員
4: }
5: public class WindowsStreamSecurityBindingElement : StreamUpgradeBindingElement
6: {
7: //省略成員
8: }
9: public class SslStreamSecurityBindingElement : StreamUpgradeBindingElement
10: {
11: //省略成員
12: }
StreamUpgradeBindingElement實現消息保護的機制被稱為Stream Upgrade。在這種機制下,經過編碼轉化成的二進制流在進入傳輸層之前,會被攔截。攔截得到的二進制流經過簽名和加密后再被重新流入傳輸層發送。還有一點需要特別指出的是:StreamUpgradeBindingElement并不會創建相應的信道,而是將功能實現的對象作為綁定參數傳入信道層,傳輸信道在將其取出并完成相應的簽名和加密工作。目前為止,只有兩種面向連接的網絡協議的傳輸信道支持Stream Upgrade,即TCP和命名管道。至于兩種具體的StreamUpgradeBindingElement,SslStreamSecurityBindingElement采用TLS/SSL協議,WindowsStreamSecurityBindingElement則基于Windows安全協議。
程序的輸出結果還反映了另一個現象:客戶憑證對最終使用的綁定協議的影響僅限于Transport安全模式。對于Mixed模式,不論采用怎樣的客戶憑證,最終實現Transport安全的綁定元素總是SslStreamSecurityBindingElement。也就是說Mixed模式下的NetTcpBinding總是采用TLS/SSL實現Transport安全。換句話說,如果你使用Mixed模式下的NetTcpBinding,你必須為服務指定一個X.509證書作為服務的憑證。
由于NetNamedPipeBinding只支持Transport安全模式,并且在該安全模式下默認使用Windows認證。所以最終實現Transport安全的總是WindowsStreamSecurityBindingElement。
1: NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.Transport);
2: binding.ListAllBindingElements();
輸出結果:
1: 1.System.ServiceModel.Channels.TransactionFlowBindingElement
2: 2.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
3: 3.System.ServiceModel.Channels.WindowsStreamSecurityBindingElement
4: 4.System.ServiceModel.Channels.NamedPipeTransportBindingElement
四、 NetMsmqBinding
我們來接著分析最后一種類型的綁定,即NetMsmqBinding,我們直接將我們定義的ListAllBindingElements擴展方法應用三個具有不同安全模式(Transport、Message和Both)的NetMsmqBinding對象上。
1: NetMsmqBinding binding = new NetMsmqBinding(NetMsmqSecurityMode.Transport);
2: Console.WriteLine("Transport:");
3: binding.ListAllBindingElements();
4:
5: binding = new NetMsmqBinding(NetMsmqSecurityMode.Message);
6: Console.WriteLine("Message:");
7: binding.ListAllBindingElements();
8:
9: binding = new NetMsmqBinding(NetMsmqSecurityMode.Both);
10: Console.WriteLine("Both:");
11: binding.ListAllBindingElements();
輸出結果:
1: Transport:
2: 1.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
3: 2.System.ServiceModel.Channels.MsmqTransportBindingElement
4: Message:
5: 1.System.ServiceModel.Channels.SymmetricSecurityBindingElement
6: 2.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
7: 3.System.ServiceModel.Channels.MsmqTransportBindingElement
8: Both:
9: 1.System.ServiceModel.Channels.SymmetricSecurityBindingElement
10: 2.System.ServiceModel.Channels.BinaryMessageEncodingBindingElement
11: 3.System.ServiceModel.Channels.MsmqTransportBindingElement
輸出結果反映了這樣一個結論:基于NetMsmqBinding的Transport安全是通過MsmqTransportBindingElement在傳輸信道中完成了,而Message安全還是通過SymmetricSecurityBindingElement采用對稱簽名和加密實現的。
五、 總結
上面我們從橫向比較各種常見的綁定在不同安全模式下具有怎樣的綁定元素列表。由于綁定元素認識安全傳輸實現的核心,所以現在我們拋開不同綁定類型的差異,直接看看Transport和Message這兩不同的安全模式最終都是由那些具體的綁定元素實現的。
Transport安全對應以下四種綁定定元素:HttpsTransportBindingElement、WindowsStreamSecurityBindingElement和SslStreamSecurityBindingElement和MsmqTransportBindingElement。其中三個基于互聯網的綁定,BasicHttpBinding、WSHttpBinding和WS2007HttpBinding)因為都是采用HTTPS實現的,所以最終的落實到HttpsTransportBindingElement上。兩種基于局域網的綁定,NetTcpBinding和NetNamePipeBinding采用Stream Upgrade的機制實現Transport安全,具體來說又落實到如下兩個綁定元素:WindowsStreamSecurityBindingElement和SslStreamSecurityBindingElement。
Message安全對應如下三種綁定元素:AsymmetricSecurityBindingElement、SymmetricSecurityBindingElement和TransportSecurityBindingElement。其中TransportSecurityBindingElement使用在Mixed安全模式下。對于Message模式,除了BasicHttpBinding使用AsymmetricSecurityBindingElement外,其余都是使用SymmetricSecurityBindingElement。


對消息進行簽名和加密分別解決了消息的一致性和機密性問題。而最終是僅僅采用簽名還是簽名與加密共用取決于契約中對消息保護級別的設置。但是具體的簽名和加密在整個WCF框架體系中如何實現?是采用對稱加密還是非對稱加密?密鑰如何而來?相信這些問題在本篇文章中你會找到答案
浙公網安備 33010602011771號