[WCF安全2]使用wsHttpBinding構建UserName受權的WCF應用程序,非SSL

  上一篇文章中介紹瞭如何使用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,大功告成!

下一篇:[WCF安全3]使用wsHttpBinding構建基於SSL與UserName受權的WCF應用程序

相關文章
相關標籤/搜索