上一篇文章中介紹瞭如何使用basicHttpBinding構建UserName受權的WCF應用程序,本文將爲您介紹如何使用wsHttpBinding構建非SSL的UserName安全受權的WCF應用程序。html
與上篇文章同樣,一樣將該示例分爲服務端與客戶端介紹。安全
1. 服務端app
(1) 實現CustomUserNameValidatoride
與上篇文章同樣,須要首先實現CustomUserNameValidator,若是還不知道如何生成CustomUserNameValidator,請參考上一篇文章。工具
1 public class CustomUserNameValidator : UserNamePasswordValidator 2 { 3 private const string USERNAME_ELEMENT_NAME = "userName"; 4 5 private const string PASSWORD_ELEMENT_NAME = "password"; 6 7 private const string FAULT_EXCEPTION_MESSAGE = "UserName or Password is incorrect!"; 8 9 public override void Validate(string userName, string password) 10 { 11 Guarder.Guard.ArgumentNotNull(userName) 12 .ArgumentNotNull(password); 13 var validateUserName = ConfigurationManager.AppSettings[USERNAME_ELEMENT_NAME]; 14 var validatePassword = ConfigurationManager.AppSettings[PASSWORD_ELEMENT_NAME]; 15 var validateCondition = userName.Equals(validateUserName) && password.Equals(validatePassword); 16 if (!validateCondition) 17 { 18 throw new FaultException(FAULT_EXCEPTION_MESSAGE); 19 } 20 } 21 }
(2) 註冊服務端證書post
這個環節是在上一篇文章中沒有的,後文中要介紹到,咱們使用了Message的方式加密消息內容,所以,咱們須要將傳輸內容加密,所以須要使用證書進行加密。咱們使用微軟自帶的"makecert.exe"命令行工具向currentUser註冊一個證書。使用Visual Studio自帶的命令行工具執行下面命令行。ui
1 makecert.exe -sr CurrentUser -ss My -a sha1 -n CN=ServerCert -sky exchange –pe
(3) 完成服務端配置文件加密
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <appSettings> 4 <add key="username" value="username"/> 5 <add key="password" value="password"/> 6 </appSettings> 7 <startup> 8 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 9 </startup> 10 <system.serviceModel> 11 <behaviors> 12 <serviceBehaviors> 13 <behavior name="securityBehavior"> 14 <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> 15 <serviceDebug includeExceptionDetailInFaults="true" /> 16 <serviceCredentials> 17 <serviceCertificate 18 findValue="ServerCert" 19 x509FindType="FindBySubjectName" 20 storeLocation="CurrentUser" 21 storeName="My"/> 22 <userNameAuthentication 23 userNamePasswordValidationMode="Custom" 24 customUserNamePasswordValidatorType="TimeSynchronizeServer.CustomUserNameValidator,TimeSynchronizeServer"/> 25 </serviceCredentials> 26 </behavior> 27 </serviceBehaviors> 28 </behaviors> 29 <bindings> 30 <wsHttpBinding> 31 <binding name="securityMessageBinding"> 32 <security mode="Message"> 33 <message clientCredentialType="UserName"/> 34 </security> 35 </binding> 36 </wsHttpBinding> 37 </bindings> 38 <services> 39 <service name="TimeSynchronizeServer.TimeSynchronizeService" 40 behaviorConfiguration="securityBehavior"> 41 <endpoint address="http://127.0.0.1/12216/TimeSynchronize" 42 binding="wsHttpBinding" bindingConfiguration="securityMessageBinding" 43 contract="TimeSynchronizeServer.ITimeSynchronizeService"> 44 <identity> 45 <dns value="ServerCert" /> 46 </identity> 47 </endpoint> 48 <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" /> 49 <host> 50 <baseAddresses> 51 <add baseAddress="http://localhost:8733/Design_Time_Addresses/TimeSynchronizeServer/TimeSynchronizeService/" /> 52 </baseAddresses> 53 </host> 54 </service> 55 </services> 56 </system.serviceModel> 57 </configuration>
其中serviceCredentials節點中添加了serviceCertificate節點,該節點用來指定使用的證書。findValue,此attribute指定的是(2)中命令行中CN=右側的字符。userNameAuthentication制定了自定義的Validator。binding節點中使用了wsHttpBinding,並將傳輸的加密方式指定爲Message,並制定UserName爲受權方式。url
2. 客戶端spa
(1) 完成客戶端配置文件
1 <?xml version="1.0" encoding="utf-8" ?> 2 <configuration> 3 <startup> 4 <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" /> 5 </startup> 6 <appSettings> 7 <add key="userName" value="username"/> 8 <add key="password" value="password"/> 9 </appSettings> 10 <system.serviceModel> 11 <bindings> 12 <wsHttpBinding> 13 <binding name="securityMessageBidning"> 14 <security mode="Message"> 15 <message clientCredentialType="UserName"/> 16 </security> 17 </binding> 18 </wsHttpBinding> 19 </bindings> 20 <client> 21 <endpoint address="http://127.0.0.1/12216/TimeSynchronize/" 22 binding="wsHttpBinding" bindingConfiguration="securityMessageBidning" 23 contract="ITimeSynchronizeService" name="DefaultBinding_ITimeSynchronizeService_ITimeSynchronizeService"> 24 <identity> 25 <dns value="ServerCert"/> 26 </identity> 27 </endpoint> 28 </client> 29 </system.serviceModel> 30 </configuration>
須要注意的是,binding節點須要與服務端配置文件中的binding配置相同。特別要注意的是,endpoint節點中的identity節點中的dns的value須要與證書名稱相同,不然會拋出一個異常,具體問題我還沒搞明白,不過搜索了一下,發現這樣可以解決問題。
(2) 完成客戶端調用代碼
1 private const string USERNAME = "userName"; 2 private const string PASSWORD = "password"; 3 4 static void Main ( string[] args ) 5 { 6 var proxy = new TimeSynchronizeServiceClient ( ); 7 var userName = ConfigurationManager.AppSettings[USERNAME]; 8 var password = ConfigurationManager.AppSettings[PASSWORD]; 9 proxy.ClientCredentials.UserName.UserName = userName; 10 proxy.ClientCredentials.UserName.Password = password; 11 proxy.ClientCredentials.ServiceCertificate.Authentication.CertificateValidationMode = 12 X509CertificateValidationMode.None; 13 var time = proxy.GetTime ( ); 14 var builder = new StringBuilder ( ); 15 builder.Append ( "Server time is:" ).Append ( " " ).Append ( time ); 16 var message = builder.ToString ( ); 17 Console.WriteLine ( message ); 18 Console.ReadKey ( ); 19 }
OK,大功告成!