[WCF安全系列]談談WCF的客戶端認證[Windows認證]
結束了服務認證的介紹之后,我們接著介紹WCF雙向認證的另一個方面,即服務對客戶端的認證,簡稱客戶端認證。客戶端認證采用的方式決定于客戶端憑證的類型,內容只要涉及基于以下三種典型客戶憑證類型的認證:Windows、用戶名和X.509證書。從編程的角度來講,Windows認證是最為簡單的認證方式。在這種認證方式下,客戶端進程運行的Window帳號對應的Windows憑證被自動作為調用服務的客戶端憑證,所以無需顯示指定具體的Windiws憑證。
如果需要另一個Windows帳號的名義調用服務,客戶端就需要通知指定Windows帳號和密碼的方式顯式地進行客戶端Windows憑證的設置。Windows憑證在WCF通過類型WindowsClientCredential表示。下面給出了WindowsClientCredential的定義,從中我們可以看到真正的憑證最終保存在類型為NetworkCredential的ClientCredential屬性中。通過該屬性,你可以指定Windows憑證的域名、用戶名和密碼。
1: public sealed class WindowsClientCredential
2: {
3: //其他成員
4: public bool AllowNtlm { get; set; }
5: public NetworkCredential ClientCredential { get; set; }
6: }
7: public class NetworkCredential : ICredentials, ICredentialsByHost
8: {
9: //其他成員
10: public string Domain { get; set; }
11: public string UserName { get; set; }
12: public string Password { get; set; }
13: public SecureString SecurePassword { get; set; }
14: }
從上面給出的代碼我們可以看到,NetworkCredential除了一個以String類型表示的Password屬性之外,還有另一外一個相關的SecurePassword屬性,其類型為SecureString。我們知道String類型具有恒定性(Immutability),一旦被創建,它將在整個進程生命周期內一直存在。因此,如果某個String對象含有諸如密碼、信用卡號碼或個人數據等敏感信息,則因為應用程序無法從計算機內存中刪除這些數據,便存在信息在使用后可能被泄漏的危險。SecureString對象與String對象的相似之處在于它也具有文本值。但是,SecureString對象的值是自動加密的,在應用程序將它標記為只讀之前可以進行修改,并且可由應用程序或.NET Framework垃圾回收器將其從計算機內存中刪除。
當你進行服務調用的時候,不管你是直接采用ChannelFactory<TChannel>創建服務代理的方式,還是通過導入元數據生成客戶端代理的方式,設置Windows憑證都很容易。ChannelFactory<TChannel>的基類ChannelFactory和ClientBase<TChannel>中都定義了一個只讀屬性ClientCredentials,該屬性的類型為ClientCredentials。對于類型ClientCredentials,我們應該不會感到陌生,因為在前面的實例演示中我們通過它實現了對服務證書認證模式的改變。我們表示Windows憑證的WindowsClientCredential對象作為只讀屬性Windows定義在ClientCredentials中,相關類型的定義如下所示。
1: public class ChannelFactory<TChannel> : ChannelFactory
2: {
3: //省略成員
4: }
5: public abstract class ChannelFactory
6: {
7: //其他成員
8: public ClientCredentials Credentials { get; }
9: }
10: public abstract class ClientBase<TChannel>
11: {
12: //其他成員
13: public ClientCredentials ClientCredentials { get; }
14: }
15: public class ClientCredentials : SecurityCredentialsManager, IEndpointBehavior
16: {
17: //其他成員
18: public WindowsClientCredential Windows { get; }
19: }
下面給出的代碼片斷為你演示了當你采用通過ChannelFactory<TChannel>創建的服務代理進行服務調用時如何進行Windows憑證的設置。
1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
2: {
3: NetworkCredential credential = channelFactory.Credentials.Windows.ClientCredential;
4: credential.Domain = "DomainName";
5: credential.UserName = "UserName";
6: credential.Password = "Password";
7:
8: ICalculator calculator = channelFactory.CreateChannel();
9: double result = calculator.Add(1, 2);
10: ...
11: }
關于WCF下的Windows認證,還有一點值得一提。上面我們給出了WindowsClientCredential的定義,不知道你是否注意到了它具有一個布爾類型的屬性AllowNtlm。這個屬性實際上涉及到關于Windows認證協議的問題。WCF集成的Windows認證是基于SSPI(Security Support Provider Interface),這是一套標準的安全編程接口,而具體安全功能的實現定義在相應的SSP(Security Support Provider)。SSPI是面向接口的安全編程成為可能,這樣的好處顯而易見:在基于不同SSP的安全環境中,你的程序都能兼容。
Windows提供了三種典型的SSP:Kerberos、NTLMSSP和SPNEGO。前兩種分別基于我們熟悉的Kerberos和NTLM,但是SPNEGO才是默認的選項。SPNEGO的全名為“Simple and Protected GSSAPI Negotiation Mechanism”,而GSSAPI(Generic Security Services Application Program Interface)是互聯網工程任務組(IETF)指定的保準的安全應用編程接口。SPNEGO,故名思義,就是通過協商(Negotiation)確定一種適合的GSS API。SPNEGO在Windows下的協商機制是這樣的:首選Kerberos,如果不可用則退而求其次,選用NTLM。
不論從安全性還是互操作性(實際上Kerberos本身就是一種標準),Kerberos都要優于NTLM,但是Keberos僅限于基于AD的域環境中使用。如果你強制要求只采用Kerberos認證,你可以通過將WindowsClientCredential的AllowNtlm屬性設成False來實現。


結束了服務認證的介紹之后,我們接著介紹WCF雙向認證的另一個方面,即服務對客戶端的認證,簡稱客戶端認證。客戶端認證采用的方式決定于客戶端憑證的類型,內容只要涉及基于以下三種典型客戶憑證類型的認證:Windows、用戶名和X.509證書。先來談談Windows認證
浙公網安備 33010602011771號