[WCF安全系列]消息的保護(hù)等級[上篇]
到目前為止,對于WCF安全傳輸?shù)娜齻€方面,我們已經(jīng)對認(rèn)證進(jìn)行了詳細(xì)的介紹,現(xiàn)在我們來關(guān)注另外兩個話題:消息的一致性和機(jī)密性,兩者又統(tǒng)稱為消息保護(hù)(Message Protection)。消息的安全等級指的是對整個消息或者消息的某個部分事實安全保護(hù)采用的等級。按照級別的由低到高,WCF支持如下三種不同的安全等級。在WCF的應(yīng)用編程接口中,消息保護(hù)級別通過如下定義的ProtectionLevel枚舉表示。
- None:不采用任何措施來保護(hù)消息的一致性和機(jī)密性;
- Sign:通過對整個消息或者消息的某個部分進(jìn)行數(shù)字簽名以確保消息的一致性;
- EncryptAndSign:通過對整個消息或者消息的某個部分同時進(jìn)行簽名和加密確保消息的一致性和機(jī)密性。
1: public enum ProtectionLevel
2: {
3: None,
4: Sign,
5: EncryptAndSign
6: }
一、消息保護(hù)級別的定義
消息的保護(hù)涉及到簽名和(或者)加密,而與簽名與加密相對的是簽名驗證和解密。要確保消息保護(hù)機(jī)制的正常進(jìn)行,客戶端和服務(wù)雙方需要首先在保護(hù)級別上達(dá)成一致,雙方按照這個約定完成屬于各自的工作。從這個意義上講,消息保護(hù)級別屬于契約的一部分,所以基于消息安全級別的編程體現(xiàn)在契約的定義中。
我們在定義服務(wù)契約的時候,可以通過ServiceContractAttribute特性的ProtectionLevel屬性為整個服務(wù)契約設(shè)置保護(hù)級別。也可以通過OperationContractAttribute特性的ProtectionLevel屬性為某個具體的操作設(shè)置保護(hù)級別。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特性設(shè)置的消息保護(hù)級別作用在正常的功能性請求消息和回復(fù)消息中。而對于出現(xiàn)異常時返回給客戶端的錯誤消息(Fault Message),我們依然需要加以保護(hù)?;阱e誤消息的保護(hù)級別可以通過FaultContractAttribute特性的ProtectionLevel進(jìn)行設(shè)置。
1: public sealed class FaultContractAttribute : Attribute
2: {
3: //其他成員
4: public ProtectionLevel ProtectionLevel {get; set; }
5: public bool HasProtectionLevel{ get; }
6: }
上述的兩種方式定義的消息保護(hù)級別都是基于整個消息的,有時候我們僅僅需要對消息中包含敏感信息的某個部分進(jìn)行簽名或者加密,那么就需要通過消息契約的方式定義整個消息的結(jié)構(gòu)了。我們通過在實體類上直接應(yīng)用MessageContractAtrribute特性來定義消息契約,而通過分別通過應(yīng)用MessageHeaderAttribute和MessageBodyMemberAttribute特性將目標(biāo)元素映射為消息報頭成員和消息主體成員。從如下代碼中可以看出,這些特性都具有一個ProtectionLevel屬性。對于MessageHeaderAttribute和MessageBodyMemberAttribute特性來說,這個屬性是通過從它們共同的基類MessageContractMemberAttribute繼承得來。通過MessageContractAtrribute特性設(shè)置的保護(hù)級別應(yīng)用于整個消息,而通過MessageContractMemberAttribute特性設(shè)置的保護(hù)級別則是基于對應(yīng)的消息內(nèi)容成員。
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: }
二、消息保護(hù)級別的作用范圍
通過上面的介紹我們知道了我們可以通過一系列基于契約(服務(wù)契約、錯誤契約和消息契約)的特性來定義消息的保護(hù)級別。那么,如果我們在這些特性中設(shè)置了不同的保護(hù)級別,它們之間具有怎樣的優(yōu)先級?WCF又采用怎樣的策略來決定最終的消息保護(hù)級別呢?
定義消息保護(hù)級別的六個特性分別位于如下圖所示的層次結(jié)構(gòu)的四個層次中。低層次可以繼承離它最近的高層次的消息保護(hù)級別。舉個具體的例子,如果通過ServiceContractAttribute特性在服務(wù)契約級別將保護(hù)級別設(shè)置為Sign,該服務(wù)契約所有的操作、操作的錯誤契約,以及操作使用到的消息契約的默認(rèn)的保護(hù)級別都變成Sign。而服務(wù)操作可以通過OperationContractAttribute特性將保護(hù)級別設(shè)置成EncryptAndSign,那么不僅僅是該操作,就連基于該操作的錯誤契約和消息契約對應(yīng)的保護(hù)級別也動變成EncryptAndSign。
三、綁定采用怎樣的消息保護(hù)級別?
上面我們著重在介紹如何在契約上定義消息的保護(hù)級別,接下來我們將關(guān)注點放在綁定上面。我們主要關(guān)注兩個問題:第一、在默認(rèn)的情況下綁定采用怎樣的保護(hù)級別?;第二、綁定的保護(hù)級別可以自定義嗎?
對于第一個問題,為了讓讀者有一個深刻的印象,我不直接告訴你答案,而是希望讀者想我一下通過編程的方式自己去獲取這個答案。在這里我們需要用到一個特殊的接口:ISecurityCapabilities。ISecurityCapabilities定義了一些簡單的屬性成員用以檢測綁定具有怎樣的安全相關(guān)的屬性,其中就包括消息的保護(hù)級別。如下面的代碼片斷所示,ISecurityCapabilities具有兩個只讀屬性SupportedRequestProtectionLevel和SupportedResponseProtectionLevel表示對應(yīng)的綁定對于請求消息和回復(fù)消息采用怎樣的保護(hù)級別。
1: public interface ISecurityCapabilities
2: {
3: //其他成員
4: ProtectionLevel SupportedRequestProtectionLevel { get; }
5: ProtectionLevel SupportedResponseProtectionLevel { get; }
6: }
那么我們現(xiàn)在就來檢測基于某種安全模式下的綁定在默認(rèn)情況下采用怎樣的消息保護(hù)級別。為了使我們的程序顯得簡潔,我寫了如下一個針對Binding類型的擴(kuò)展方法PrintProtectionLevel,用于輸出綁定對請求和回復(fù)消息采用的保護(hù)級別。
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: }
現(xiàn)在我們通過下面的代碼檢測BasicHttpBinding針對四種不同的安全級別默認(rèn)采用怎樣的消息保護(hù)級別。從輸出結(jié)果我們可以很清楚的看到,除了TransportCredentialOnly之外,BasicHttpBinding都是采用EncryptAndSign保護(hù)級別。
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");
輸出結(jié)果:
Security Mode Request Response
Transport EncryptAndSign EncryptAndSign
Message EncryptAndSign EncryptAndSign
Mixed EncryptAndSign EncryptAndSign
TransportCredentialOnly None None
如果你將上面的測試程序用于其它的綁定(WSHttpBinding/WS2007DualHttpBinding、WSDualHttpBinding、NetTcpBinding、NetNamedPipeBinding以及Message和Both模式下的NetMsmqBinding)你會發(fā)現(xiàn)當(dāng)安全被開啟的情況下,這些綁定默認(rèn)都是采用最高的消息保護(hù)級別EncryptAndSign。
但是我們編寫的擴(kuò)展方法不能用于Transport模式下的NetMsmqBinding。不過在表示NetMsmqBinding基于Transport安全的類型MsmqTransportSecurity中具有一個MsmqProtectionLevel屬性返回采用的消息保護(hù)級別。從應(yīng)用在該屬性上的DefaultValueAttribute特性的定義中,我們可以直接看出NetMsmqBinding在Transport模式下默認(rèn)采用的消息保護(hù)級別為Sign。
public sealed class MsmqTransportSecurity
{
//其他成員
[DefaultValue(1)]
public ProtectionLevel MsmqProtectionLevel { get; set; }
}
上面我們討論了對于我們常用的綁定針對相應(yīng)的安全模式默認(rèn)采用的消息保護(hù)級別,接下來我們討論的話題是:這些默認(rèn)的保護(hù)級別可以自定義嗎?答案是“部分可以”。具體來說,你只可以修改三個基于局域網(wǎng)的綁定針對Transport安全模式下的消息保護(hù)級別。對于NetMsmqBinding,你可以通過MsmqTransportSecurity的MsmqProtectionLevel進(jìn)行設(shè)置。而用于設(shè)置NetTcpBinding和NetNamedPipeBinding基于Transport安全的TcpTransportSecurity和NamedPipeTransportSecurity類型中,都具有ProtectionLevel屬性用于進(jìn)行消息保護(hù)級別的顯式設(shè)置。而且從應(yīng)用在該屬性上的DefaultValueAttribute特性中我們可以看出默認(rèn)值為EncryptAndSign。你可以通過編程或者配置的方式來指定NetTcpBinding、NetNamedPipeBinding和NetMsmqBinding在Transport安全模式下的消息保護(hù)級別。
public sealed class TcpTransportSecurity
{
//其他成員
[DefaultValue(2)]
public ProtectionLevel ProtectionLevel { get; set; }
}
public sealed class NamedPipeTransportSecurity
{
//其他成員
[DefaultValue(2)]
public ProtectionLevel ProtectionLevel { get; set; }
}


到目前為止,對于WCF安全傳輸?shù)娜齻€方面,我們已經(jīng)對認(rèn)證進(jìn)行了詳細(xì)的介紹,現(xiàn)在我們來關(guān)注另外兩個話題:消息的一致性和機(jī)密性,兩者又統(tǒng)稱為消息保護(hù)(Message Protection)。消息安全等級指的是對整個消息或者消息的某個部分實施安全保護(hù)采用的等級。按照級別由低到高,WCF支持三種不同的安全等級

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