954
技術社區[雲棲]
[WCF安全係列]消息的保護等級[上篇]
到目前為止,對於WCF安全傳輸的三個方麵,我們已經對認證進行了詳細的介紹,現在我們來關注另外兩個話題:消息的一致性和機密性,兩者又統稱為消息保護(Message Protection)。消息的安全等級指的是對整個消息或者消息的某個部分事實安全保護采用的等級。按照級別的由低到高,WCF支持如下三種不同的安全等級。在WCF的應用編程接口中,消息保護級別通過如下定義的ProtectionLevel枚舉表示。
- None:不采用任何措施來保護消息的一致性和機密性;
- Sign:通過對整個消息或者消息的某個部分進行數字簽名以確保消息的一致性;
- EncryptAndSign:通過對整個消息或者消息的某個部分同時進行簽名和加密確保消息的一致性和機密性。
1: public enum ProtectionLevel
2: {
3: None,
4: Sign,
5: EncryptAndSign
6: }
消息的保護涉及到簽名和(或者)加密,而與簽名與加密相對的是簽名驗證和解密。要確保消息保護機製的正常進行,客戶端和服務雙方需要首先在保護級別上達成一致,雙方按照這個約定完成屬於各自的工作。從這個意義上講,,所以。
我們在定義服務契約的時候,可以通過ServiceContractAttribute特性的ProtectionLevel屬性為整個服務契約設置保護級別。也可以通過OperationContractAttribute特性的ProtectionLevel屬性為某個具體的操作設置保護級別。ProtectionLevel屬性在這兩個特性中的定義如下。
1: public sealed class ServiceContractAttribute : Attribute
2: {
3: //其他成員
4: public ProtectionLevel ProtectionLevel { get; set; }
5: public bool HasProtectionLevel{ get; }
6: }
7: public sealed class OperationContractAttribute : Attribute
8: {
9: //其他成員
10: public ProtectionLevel ProtectionLevel {get; set; }
11: public bool HasProtectionLevel{ get; }
12: }
通過ServiceContractAttribute和OperationContractAttribute特性設置的消息保護級別作用在正常的功能性請求消息和回複消息中。而對於出現異常時返回給客戶端的錯誤消息(Fault Message),我們依然需要加以保護。基於錯誤消息的保護級別可以通過FaultContractAttribute特性的ProtectionLevel進行設置。
1: public sealed class FaultContractAttribute : Attribute
2: {
3: //其他成員
4: public ProtectionLevel ProtectionLevel {get; set; }
5: public bool HasProtectionLevel{ get; }
6: }
上述的兩種方式定義的消息保護級別都是基於整個消息的,有時候我們僅僅需要對消息中包含敏感信息的某個部分進行簽名或者加密,那麼就需要通過消息契約的方式定義整個消息的結構了。我們通過在實體類上直接應用MessageContractAtrribute特性來定義消息契約,而通過分別通過應用MessageHeaderAttribute和MessageBodyMemberAttribute特性將目標元素映射為消息報頭成員和消息主體成員。從如下代碼中可以看出,這些特性都具有一個ProtectionLevel屬性。對於MessageHeaderAttribute和MessageBodyMemberAttribute特性來說,這個屬性是通過從它們共同的基類MessageContractMemberAttribute繼承得來。通過MessageContractAtrribute特性設置的保護級別應用於整個消息,而通過MessageContractMemberAttribute特性設置的保護級別則是基於對應的消息內容成員。
1: public sealed class MessageContractAttribute : Attribute
2: {
3: //其他成員
4: public ProtectionLevel ProtectionLevel {get; set; }
5: public bool HasProtectionLevel{ get; }
6: }
7: public abstract class MessageContractMemberAttribute : Attribute
8: {
9: //其他成員
10: public ProtectionLevel ProtectionLevel {get; set; }
11: public bool HasProtectionLevel{ get; }
12: }
13: public class MessageHeaderAttribute : MessageContractMemberAttribute
14: {
15: //省略成員
16: }
17: public class MessageBodyMemberAttribute : MessageContractMemberAttribute
18: {
19: //省略成員
20: }
通過上麵的介紹我們知道了我們可以通過一係列基於契約(服務契約、錯誤契約和消息契約)的特性來定義消息的保護級別。那麼,如果我們在這些特性中設置了不同的保護級別,它們之間具有怎樣的優先級?WCF又采用怎樣的策略來決定最終的消息保護級別呢?
定義消息保護級別的六個特性分別位於如下圖所示的層次結構的四個層次中。。舉個具體的例子,如果通過ServiceContractAttribute特性在服務契約級別將保護級別設置為Sign,該服務契約所有的操作、操作的錯誤契約,以及操作使用到的消息契約的默認的保護級別都變成Sign。而服務操作可以通過OperationContractAttribute特性將保護級別設置成EncryptAndSign,那麼不僅僅是該操作,就連基於該操作的錯誤契約和消息契約對應的保護級別也動變成EncryptAndSign。
上麵我們著重在介紹如何在契約上定義消息的保護級別,接下來我們將關注點放在綁定上麵。我們主要關注兩個問題:第一、;第二、?
對於第一個問題,為了讓讀者有一個深刻的印象,我不直接告訴你答案,而是希望讀者想我一下通過編程的方式自己去獲取這個答案。在這裏我們需要用到一個特殊的接口:ISecurityCapabilities。ISecurityCapabilities定義了一些簡單的屬性成員用以檢測綁定具有怎樣的安全相關的屬性,其中就包括消息的保護級別。如下麵的代碼片斷所示,ISecurityCapabilities具有兩個隻讀屬性SupportedRequestProtectionLevel和SupportedResponseProtectionLevel表示對應的綁定對於請求消息和回複消息采用怎樣的保護級別。
1: public interface ISecurityCapabilities
2: {
3: //其他成員
4: ProtectionLevel SupportedRequestProtectionLevel { get; }
5: ProtectionLevel SupportedResponseProtectionLevel { get; }
6: }
那麼我們現在就來檢測基於某種安全模式下的綁定在默認情況下采用怎樣的消息保護級別。為了使我們的程序顯得簡潔,我寫了如下一個針對Binding類型的擴展方法PrintProtectionLevel,用於輸出綁定對請求和回複消息采用的保護級別。
1: public static class BindingExtension
2: {
3: public static void PrintProtectionLevel(this Binding binding, string securityMode)
4: {
5: var bindingParameters = new BindingParameterCollection();
6: var requestProtectionLevel = binding.GetProperty<ISecurityCapabilities>(bindingParameters).SupportedRequestProtectionLevel;
7: var responseProtectionLevel = binding.GetProperty<ISecurityCapabilities>(bindingParameters).SupportedResponseProtectionLevel;
8: Console.WriteLine("{0, -25}{1, -20}{2,-20}", securityMode, requestProtectionLevel, responseProtectionLevel);
9: }
10: }
現在我們通過下麵的代碼檢測BasicHttpBinding針對四種不同的安全級別默認采用怎樣的消息保護級別。從輸出結果我們可以很清楚的看到,除了TransportCredentialOnly之外,BasicHttpBinding都是采用EncryptAndSign保護級別。
1: Console.WriteLine("{0, -25}{1, -20}{2,-20}", "Security Mode","Request", "Response");
2: var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport);
3: binding.PrintProtectionLevel("Transport");
4:
5: binding = new BasicHttpBinding(BasicHttpSecurityMode.Message);
6: binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.Certificate;
7: binding.PrintProtectionLevel("Message");
8:
9: binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportWithMessageCredential);
10: binding.PrintProtectionLevel("Mixed");
11:
12: binding = new BasicHttpBinding(BasicHttpSecurityMode.TransportCredentialOnly);
13: binding.PrintProtectionLevel("TransportCredentialOnly");
輸出結果:
Security Mode Request Response
Transport EncryptAndSign EncryptAndSign
Message EncryptAndSign EncryptAndSign
Mixed EncryptAndSign EncryptAndSign
TransportCredentialOnly None None
如果你將上麵的測試程序用於其它的綁定(WSHttpBinding/WS2007DualHttpBinding、WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding以及Message和Both模式下的NetMsmqBinding)你會發現。
但是。不過在表示NetMsmqBinding基於Transport安全的類型MsmqTransportSecurity中具有一個屬性返回采用的消息保護級別。從應用在該屬性上的DefaultValueAttribute特性的定義中,我們可以直接看出NetMsmqBinding在Transport模式下默認采用的消息保護級別為。
public sealed class MsmqTransportSecurity
{
//其他成員
[DefaultValue(1)]
public ProtectionLevel MsmqProtectionLevel { get; set; }
}
上麵我們討論了對於我們常用的綁定針對相應的安全模式默認采用的消息保護級別,接下來我們討論的話題是:這些默認的保護級別可以自定義嗎?答案是“部分可以”。具體來說,你隻可以修改三個基於局域網的綁定針對Transport安全模式下的消息保護級別。對於NetMsmqBinding,你可以通過MsmqTransportSecurity的MsmqProtectionLevel進行設置。而用於設置NetTcpBinding和NetNamedPipeBinding基於Transport安全的TcpTransportSecurity和NamedPipeTransportSecurity類型中,都具有ProtectionLevel屬性用於進行消息保護級別的顯式設置。而且從應用在該屬性上的DefaultValueAttribute特性中我們可以看出默認值為EncryptAndSign。。
public sealed class TcpTransportSecurity
{
//其他成員
[DefaultValue(2)]
public ProtectionLevel ProtectionLevel { get; set; }
}
public sealed class NamedPipeTransportSecurity
{
//其他成員
[DefaultValue(2)]
public ProtectionLevel ProtectionLevel { get; set; }
}
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-26 16:34:28