WCF簡單教程(8)安全-Windows認證

技術小胖子發表於2017-11-09

第八篇:WCF安全

WCF提供了非常豐富的加密機制與稽核機制,以保證對外提供的服務安全可靠。本文是簡單教程,所以只挑其中的一小部分來聊聊。

先來看看最簡單的Windows認證。

所謂Windows認證,是指客戶端訪問時,要提供服務端認可的Windows使用者身份。

1、服務端

安全配置主要體現在App.config中:


  1. <?xml version=“1.0” encoding=“utf-8” ?> 
  2. <configuration> 
  3. <system.serviceModel> 
  4.    <services> 
  5.       <service name=“Server.DataProvider”> 
  6. <!– 本例中使用netTcpBinding,注意指定了一個名為tcpBinding的設定,見下文 –> 
  7.         <endpoint address=“” binding=“netTcpBinding” contract=“Server.IData” bindingConfiguration=“tcpBinding” /> 
  8.         <host> 
  9.           <baseAddresses> 
  10.             <add baseAddress=“net.tcp://localhost:8081/wcf” /> 
  11.           </baseAddresses> 
  12.         </host> 
  13.       </service> 
  14.     </services> 
  15.  
  16.     <!–客戶端的身份認證是設定在bindings節中的–> 
  17.     <bindings> 
  18. <!–注意此節要與前面的binding匹配,表示為netTcpBinding方式的繫結進行配置–> 
  19.       <netTcpBinding> 
  20. <!–定義一個名為tcpBinding的設定,就是前面endpoint中用到的–> 
  21.         <binding name=“tcpBinding”> 
  22. <!–使用Message方式的加密,至於它與Transport方式的區別,可先忽略,後面再講–> 
  23.           <security mode=“Message”> 
  24. <!–指定客戶端認證使用Windows方式–> 
  25.             <message clientCredentialType=“Windows” /> 
  26.           </security> 
  27.         </binding> 
  28.       </netTcpBinding> 
  29.     </bindings> 
  30.   </system.serviceModel> 
  31. </configuration> 

契約實現類我們修改一下,方便看到呼叫者的身份:


  1. using System; 
  2. using System.ServiceModel; 
  3.  
  4. namespace Server 
  5.     [ServiceBehavior] 
  6.     public class DataProvider : IData 
  7.     { 
  8.         public string SayHello() 
  9.         { 
  10. //WindowsIdentity即代表訪問者的身份標識 
  11.             return string.Format(“Hello {0}”, OperationContext.Current.ServiceSecurityContext.WindowsIdentity.Name); 
  12.         } 
  13.     } 


2、客戶端

客戶端要對應調整App.config:


  1. <?xml version=“1.0” encoding=“utf-8” ?> 
  2. <configuration> 
  3.   <system.serviceModel> 
  4.     <client> 
  5. <!–定義endpoint時指定使用特定的配置,另外這個IP是一會兒執行服務端的機器的IP–> 
  6.       <endpoint binding=“netTcpBinding” contract=“Server.IData” address=“net.tcp://192.168.90.90:8081/wcf” name=“DataProvider” bindingConfiguration=“tcp” /> 
  7.     </client> 
  8. <!–客戶端與服務端的bindings節設定一致–> 
  9.     <bindings> 
  10.       <netTcpBinding> 
  11.         <binding name=“tcp”> 
  12.           <security mode=“Message”> 
  13.             <message clientCredentialType=“Windows” /> 
  14.           </security> 
  15.         </binding> 
  16.       </netTcpBinding> 
  17.     </bindings> 
  18.   </system.serviceModel> 
  19. </configuration> 



然後是程式碼,要指定訪問時客戶端使用的使用者名稱密碼:


  1. using System; 
  2. using System.ServiceModel; 
  3. using System.ServiceModel.Channels; 
  4.  
  5. namespace Client 
  6.     class Program 
  7.     { 
  8.         static void Main(string[] args) 
  9.         { 
  10. //建立一個ChannelFactory,指定使用名為DataProvider的配置 
  11.             var factory = new ChannelFactory<Server.IData>(“DataProvider”); 
  12.  
  13. //指定使用者名稱、密碼,這個Test是服務端Windows上的一個普通帳戶,如果加入了域,還要指定ClientCredential.Domain
  14. factory.Credentials.Windows.ClientCredential.UserName= “Test”
  15. factory.Credentials.Windows.ClientCredential.Password = “test”
  16.  
  17. //建立Channel,並呼叫SayHello方法 
  18.             var proxy = factory.CreateChannel(); 
  19.             Console.WriteLine(proxy.SayHello()); 
  20.             ((IChannel)proxy).Close(); 
  21.         } 
  22.     } 

其中的指定的使用者名稱與密碼是服務端存在的一個Windows使用者。



OK,在兩臺機器上分別執行服務端和客戶端,能夠正常完成呼叫,輸出“Hello Test-PCTest”,這個Test-PCTest就是我們呼叫時傳遞的使用者身份,注意是“機器名使用者名稱”的形式,如果是AD環境,那麼就是“域使用者名稱”的形式。

如果給定一個錯誤的使用者名稱密碼,則呼叫時會收到Exception:


  1. 未處理的異常:  System.ServiceModel.Security.SecurityNegotiationException: 呼叫方未由服務進行身份驗證。 —> System.ServiceModel.FaultException: 無法滿足對安全令牌的請求,因為身份驗證失敗。 
  2.    在 System.ServiceModel.Security.SecurityUtils.ThrowIfNegotiationFault(Message message, EndpointAddress target) 
  3.    在 System.ServiceModel.Security.SspiNegotiationTokenProvider.GetNextOutgoingMessageBody(Message incomingMessage, SspiNegotiationTokenProviderState sspiState) 

是一個身份驗證失敗的異常。



用Windows帳戶來做驗證,其實是個挺麻煩的事情,只有較少的系統是這麼做的,我們還是希望能用更通用的使用者名稱密碼來進行身份驗證,下一篇我們就來看看如何做。

 

 

     本文轉自 BoyTNT 51CTO部落格,原文連結:http://blog.51cto.com/boytnt/815117,如需轉載請自行聯絡原作者

     


相關文章