[WCF安全係列]談談WCF的客戶端認證[X.509證書認證]
前麵介紹Windows認證和用戶名/密碼認證這兩種典型的客戶端認證模式,我們最後來介紹最後一種客戶端認證方式,即客戶端憑證類型為X.509證書時服務端采用的認證,簡稱為證書認證。我們照例先看看看客戶端證書憑證如何設置設置。
在服務認證一文中,我們知道了基於X.509證書證書的服務憑證通過X509CertificateRecipientServiceCredential類型表示。與之對應地,客戶端憑證對應的類型是X509CertificateInitiatorClientCredential。如下麵的定義所示,在終結點行為 ClientCredentials中,具有一個隻讀的ClientCertificate屬性,其類型就是X509CertificateInitiatorClientCredential。該類型實際上是對一個X509Certificate2類型對象的封裝,我們可以通過兩個SetCertificate方法重載以證書引用的方式指定某個具體的X.509證書作為客戶端的憑證。
1: public class ClientCredentials : SecurityCredentialsManager, IEndpointBehavior
2: {
3: //其他成員
4: public X509CertificateInitiatorClientCredential ClientCertificate { get; }
5: }
6: public sealed class X509CertificateInitiatorClientCredential
7: {
8: //其他成員
9: public void SetCertificate(string subjectName, StoreLocation storeLocation, StoreName storeName);
10: public void SetCertificate(StoreLocation storeLocation, StoreName storeName, X509FindType findType, object findValue);
11: public X509Certificate2 Certificate { get; set; }
12: }
在下麵給出服務調用代碼中,我們通過編程的方式為ChannelFactory<TChannel>設置了一個基於X.509證書的客戶端憑證。
1: using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
2: {
3: channelFactory.Credentials.ClientCertificate.SetCertificate(
4: StoreLocation.LocalMachine,
5: StoreName.TrustedPeople,
6: X509FindType.FindBySubjectName,
7: "Foo");
8: ICalculator calculator = channelFactory.CreateChannel();
9: double result = calculator.Add(1, 2);
10: //...
11: }
終結點行為ClientCredentials同樣為客戶端(默認)證書的設置定義相應的配置。在下麵給出的XML片斷中,我們通過配置的方式為終結點憑證指定了一個X.509證書。這個證書將作為服務代理對象(通過ChannelFactory<TChannel>創建的代理,或者是直接實例化通過元數據導入生成的服務代理類型)的默認客戶憑證,而該憑證可以通過編程進行動態更改。
1: <system.serviceModel>
2: ...
3: <behaviors>
4: <endpointBehaviors>
5: <behavior name="defaultClientCert">
6: <clientCredentials>
7: <clientCertificate storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" findValue="Foo"/>
8: </clientCredentials>
9: </behavior>
10: </endpointBehaviors>
11: </behaviors>
12: </system.serviceModel>
關於基於證書的客戶端認證,你可以與基於證書的服務認證進行類比。對於服務認證,服務在寄宿的時候指定某個X.509證書作為服務的憑證。客戶端在默認的情況下會以模式對服務證書進行認證,也可以通過ClientCredentials這個終結點行為指定不同的認證模式。對於客戶端認證,認證方變成了服務本身,服務端對客戶證書的認證也采用相同的策略:默認認證模式為,但借助ServiceCredentials這個服務行為來指定不同的認證模式。
下麵給出了服務端進行客戶端證書認證模式設置對應的相關類型的定義。服務行為ServiceCredentials中具有一個隻讀的ClientCertificate屬性,類型為X509CertificateInitiatorServiceCredential(對應於服務認證中的X509CertificateRecipientClientCredential)。X509CertificateInitiatorServiceCredential定義了隻讀屬性Authentication,其類型為X509ClientCertificateAuthentication(對應於服務認證中的X509ServiceCertificateAuthentication)。和X509ServiceCertificateAuthentication定義類似,你可以通過X509ClientCertificateAuthentication設置不同的認證模式(None、PeerTrust、ChainTrust、PeerOrChainTrust、Custom)。當你選擇Custom模式的時候,你需要通過CustomCertificateValidator屬性設置一個自定義的X509CertificateValidator。
1: public class ServiceCredentials : SecurityCredentialsManager, IServiceBehavior
2: {
3: //其他成員
4: public X509CertificateInitiatorServiceCredential ClientCertificate { get; }
5: }
6: public sealed class X509CertificateInitiatorServiceCredential
7: {
8: //其他成員
9: public X509ClientCertificateAuthentication Authentication { get; }
10: public X509Certificate2 Certificate { get; set; }
11: }
12: public class X509ClientCertificateAuthentication
13: {
14: //其他成員
15: public X509CertificateValidationMode CertificateValidationMode { get; set; }
16: public X509CertificateValidator CustomCertificateValidator { get; set; }
17: }
下麵的代碼演示了在對服務進行自我寄宿的情況下,如何設置對客戶端證書進行認證的模式,在這裏將認證模式設置成了PeerOrChainTrust。
1: using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
2: {
3: ServiceCredentials serviceCredentials = host.Description.Behaviors.Find<ServiceCredentials>();
4: if (null == serviceCredentials)
5: {
6: serviceCredentials = new ServiceCredentials();
7: host.Description.Behaviors.Add(serviceCredentials);
8: }
9: serviceCredentials.ClientCertificate.Authentication.CertificateValidationMode = X509CertificateValidationMode.PeerOrChainTrust;
10: host.Open();
11: //...
12: }
我們推薦的依舊是采用配置的方式,上麵這段代碼中設置的服務行為可以通過下麵一端配置來表示。
1: <system.serviceModel>
2: ...
3: <behaviors>
4: <serviceBehaviors>
5: <behavior name="setCertAuthentication">
6: <serviceCredentials>
7: <clientCertificate>
8: <authentication certificateValidationMode="PeerOrChainTrust"/>
9: </clientCertificate>
10: </serviceCredentials>
11: </behavior>
12: </serviceBehaviors>
13: </behaviors>
14: </system.serviceModel>
微信公眾賬號:大內老A
微博:www.weibo.com/artech
如果你想及時得到個人撰寫文章以及著作的消息推送,或者想看看個人推薦的技術資料,可以掃描左邊二維碼(或者長按識別二維碼)關注個人公眾號(原來公眾帳號蔣金楠的自媒體將會停用)。
本文版權歸作者和博客園共有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁麵明顯位置給出原文連接,否則保留追究法律責任的權利。
最後更新:2017-10-26 16:34:31