[WCF安全1]使用basicHttpBinding构建UserName授权的WCF应用程序

  最近到了新公司,leader让我研究一下WCF的传输安全机制。以前也做过WCF的应用,但是很少涉及安全方面的东西。所以,花了三天的时间研究了一下如何在WCF的应用程序中配置安全。在这个系列文章中,我会将我的一些心得分享给大家,希望对大家有所帮助。

  我所做的研究主要是使用UserName的验证方式,对请求进行验证,本文主要介绍使用basicHttpBinding进行验证,后续两篇文章中将针对wsHttpBinding介绍使用http方式验证以及https(SSL)方式验证。

  首先,想跟大家说明,这几篇帖子,我的重点在于如何配置WCF应用程序,使你的WCF程序能够使用UserName的安全验证;而不在于如何建立WCF应用程序,如果大家想了解关于建立WCF应用程序的相关知识,请参考MSDN相关文档。

  Let's go!

  我将我的应用程序分为服务端与访问端,下面让我们分别看服务端与客户端。

1. 服务端

  (1) 创建CustomUserNameValidator

  CustomUserNameValidator从UserNamePasswordValidator类继承,并且需要实现抽象方法Validate,可以在其中实现用户名密码验证逻辑,如果验证不成功,抛出异常。

 

 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) 完成服务端配置文件

  服务端配置文件:

 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   <system.serviceModel>
 7     <behaviors>
 8       <serviceBehaviors>
 9         <behavior name="customBehavior">
10           <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
11           <serviceDebug includeExceptionDetailInFaults="true" />
12           <serviceCredentials>
13             <userNameAuthentication 
14               userNamePasswordValidationMode="Custom" 
15               customUserNamePasswordValidatorType="EmployeesHost.CustomUserNameValidator, EmployeesHost"/>
16           </serviceCredentials>
17         </behavior>
18       </serviceBehaviors>
19     </behaviors>
20     <bindings >
21       <basicHttpBinding>
22         <binding name="EmployeeQueryBinding_BasicHttp">
23           <security mode="TransportCredentialOnly">
24             <transport clientCredentialType="Basic"/>
25           </security>
26         </binding>
27       </basicHttpBinding>
28     </bindings>
29     <services>
30       <service name="EmployeesHost.EmployeesQueryService" behaviorConfiguration="customBehavior">
31         <!--For basic http binding endpoint-->
32         <endpoint address="http://127.0.0.1:12215/EmployeeQuery" binding="basicHttpBinding" 
33                   bindingConfiguration="EmployeeQueryBinding_BasicHttp"
34                   contract="EmployeesHost.IEmployeesQueryService">
35           <identity>
36             <dns value="localhost" />
37           </identity>
38         </endpoint>
39         <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
40         <host>
41           <baseAddresses>
42             <add baseAddress="http://127.0.0.1:8733/Design_Time_Addresses/EmployeesHost/EmployeesQueryService/" />
43           </baseAddresses>
44         </host>
45       </service>
46     </services>
47   </system.serviceModel>
48   <appSettings>
49     <add key="userName" value="username"/>
50     <add key="password" value="password"/>
51   </appSettings>
52 </configuration>

  需要注意的是,serviceCredentials节点中需要按照上面文件中的写法。binding节点中也需要严格按照上面文件中所写。、

  (3) 完成ServiceHost启动

  启动ServiceHost代码:

 1 static void Main(string[] args)
 2 {
 3     var host = new ServiceHost(typeof(EmployeesQueryService));
 4     host.Open();
 6     Console.WriteLine("Service Host opened, press <s> to stop...");
 7     var key = Console.ReadKey();
 8     if (key.Key == ConsoleKey.S)
 9     {
10       host.Close();
11     }
12     Console.WriteLine("Press any key to quit...");
13     Console.ReadKey();
14 }

2. 客户端

  (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   <system.serviceModel>
 7     <bindings>
 8       <basicHttpBinding>
 9         <binding name="DefaultBinding_IEmployeesQueryService">
10           <security mode="TransportCredentialOnly">
11             <transport clientCredentialType="Basic"/>
12           </security>
13         </binding>
14       </basicHttpBinding>
15     </bindings>
16     <client>
17       <!--For basic http binding endpoint-->
18       <endpoint address="http://127.0.0.1:12215/EmployeeQuery/"
19                 binding="basicHttpBinding" bindingConfiguration="DefaultBinding_IEmployeesQueryService"
20                 contract="IEmployeesQueryService" name="DefaultBinding_IEmployeesQueryService_IEmployeesQueryService" />
21     </client>
22   </system.serviceModel>
23   <appSettings>
24     <add key="userName" value="username"/>
25     <add key="password" value="password"/>
26   </appSettings>
27 </configuration>

  注意,客户端配置文件中的binding节点,需要与服务端的binding节点写法相同。

  (2) 客户端调用代码

1 var userName = ConfigurationManager.AppSettings[USERNAME_ELEMENT_NAME];
2var password = ConfigurationManager.AppSettings[PASSWORD_ELEMENT_NAME];
3 mProxy.ClientCredentials.UserName.UserName = userName;
4 mProxy.ClientCredentials.UserName.Password = password;
5 var data = mProxy.GetData();

 

OK,大功告成,运行,ok。

下一篇:[WCF安全2]使用wsHttpBinding构建UserName授权的WCF应用程序,非SSL

posted @ 2013-08-26 20:55  yafeya  阅读(532)  评论(3编辑  收藏  举报