最近到了新公司,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,可以在其中实现用户名密码验证逻辑,如果验证不成功,抛出异常。

 

 public class CustomUserNameValidator : UserNamePasswordValidator
{
  private const string USERNAME_ELEMENT_NAME = "userName"; private const string PASSWORD_ELEMENT_NAME = "password"; private const string FAULT_EXCEPTION_MESSAGE = "UserName or Password is incorrect!"; public override void Validate(string userName, string password)
{
  Guarder.Guard.ArgumentNotNull(userName)
      .ArgumentNotNull(password);
var validateUserName = ConfigurationManager.AppSettings[USERNAME_ELEMENT_NAME];
var validatePassword = ConfigurationManager.AppSettings[PASSWORD_ELEMENT_NAME];
var validateCondition = userName.Equals(validateUserName) && password.Equals(validatePassword);
if (!validateCondition)
{
  throw new FaultException(FAULT_EXCEPTION_MESSAGE);
}
}
}

  (2) 完成服务端配置文件

  服务端配置文件:

 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="customBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="EmployeesHost.CustomUserNameValidator, EmployeesHost"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings >
<basicHttpBinding>
<binding name="EmployeeQueryBinding_BasicHttp">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="EmployeesHost.EmployeesQueryService" behaviorConfiguration="customBehavior">
<!--For basic http binding endpoint-->
<endpoint address="http://127.0.0.1:12215/EmployeeQuery" binding="basicHttpBinding"
bindingConfiguration="EmployeeQueryBinding_BasicHttp"
contract="EmployeesHost.IEmployeesQueryService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:8733/Design_Time_Addresses/EmployeesHost/EmployeesQueryService/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
<appSettings>
<add key="userName" value="username"/>
<add key="password" value="password"/>
</appSettings>
</configuration>

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

  (3) 完成ServiceHost启动

  启动ServiceHost代码:

 static void Main(string[] args)
{
var host = new ServiceHost(typeof(EmployeesQueryService));
host.Open();
Console.WriteLine("Service Host opened, press <s> to stop...");
var key = Console.ReadKey();
if (key.Key == ConsoleKey.S)
{
  host.Close();
}
Console.WriteLine("Press any key to quit...");
Console.ReadKey();
14 }

2. 客户端

  (1) 客户端配置文件:

 <?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="DefaultBinding_IEmployeesQueryService">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<!--For basic http binding endpoint-->
<endpoint address="http://127.0.0.1:12215/EmployeeQuery/"
binding="basicHttpBinding" bindingConfiguration="DefaultBinding_IEmployeesQueryService"
contract="IEmployeesQueryService" name="DefaultBinding_IEmployeesQueryService_IEmployeesQueryService" />
</client>
</system.serviceModel>
<appSettings>
<add key="userName" value="username"/>
<add key="password" value="password"/>
</appSettings>
</configuration>

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

  (2) 客户端调用代码

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

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

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

[WCF安全1]使用basicHttpBinding构建UserName授权的WCF应用程序的更多相关文章

  1. [WCF安全2]使用wsHttpBinding构建UserName授权的WCF应用程序,非SSL

    上一篇文章中介绍了如何使用basicHttpBinding构建UserName授权的WCF应用程序,本文将为您介绍如何使用wsHttpBinding构建非SSL的UserName安全授权的WCF应用程 ...

  2. [WCF安全3]使用wsHttpBinding构建基于SSL与UserName授权的WCF应用程序

    上一篇文章中介绍了如何使用wsHttpBinding构建UserName授权的WCF应用程序,本文将为您介绍如何使用wsHttpBinding构建基于SSL的UserName安全授权的WCF应用程序. ...

  3. 构建RESTful风格的WCF服务

    构建RESTful风格的WCF服务 RESTful Wcf是一种基于Http协议的服务架构风格. 相较 WCF.WebService 使用 SOAP.WSDL.WS-* 而言,几乎所有的语言和网络平台 ...

  4. WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇]

    原文:WCF技术剖析之二十六:如何导出WCF服务的元数据(Metadata)[实现篇] 元数据的导出就是实现从ServiceEndpoint对象向MetadataSet对象转换的过程,在WCF元数据框 ...

  5. WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇]

    原文:WCF技术剖析之二十二: 深入剖析WCF底层异常处理框架实现原理[中篇] 在[上篇]中,我们分别站在消息交换和编程的角度介绍了SOAP Fault和FaultException异常.在服务执行过 ...

  6. WCF开发实战系列一:创建第一个WCF服务

    WCF开发实战系列一:创建第一个WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 在这个实战中我们将使用DataContract,ServiceContract ...

  7. WCF开发实战系列二:使用IIS发布WCF服务

    WCF开发实战系列二:使用IIS发布WCF服务 (原创:灰灰虫的家http://hi.baidu.com/grayworm) 上一篇中,我们创建了一个简单的WCF服务,在测试的时候,我们使用VS200 ...

  8. 利用ant脚本 自动构建svn增量/全量 系统程序升级包【转】

    引文:我们公司是做自己使用产品,迭代更新周期短,每次都花费较多时间和精力打包做增量更新,发现了一篇文章用于 自动构建svn增量/全量 系统程序升级包,收藏之,希望可以通过学习,更加简化我们的工作. 文 ...

  9. 知道WCF的地址用工厂通道方式快速调用WCF

    知道WCF的地址用工厂通道方式快速调用WCF  1 using System;  2 using System.ServiceModel;  3 using System.ServiceModel.D ...

随机推荐

  1. Android集成百度地图SDK

    本Demo中所含功能 1:定位,显示当前位置 2:地图多覆盖物(地图描点.弹出该点的具体信息) 3:坐标地址互相换算 4:POI兴趣点检索 5:线路查询(步行,驾车,公交) 6:绘制线路(OpenGL ...

  2. java爬取网页内容 简单例子(1)——使用正则表达式

    [本文介绍] 爬取别人网页上的内容,听上似乎很有趣的样子,只要几步,就可以获取到力所不能及的东西,例如呢?例如天气预报,总不能自己拿着仪器去测吧!当然,要获取天气预报还是用webService好.这里 ...

  3. python collections模块 计数器(counter)

    一.计数器(counter) Counter是对字典类型的补充,用于追踪值的出现次数. ps:具备字典的所有功能 + 自己的功能 把我写入的元素出现的多少次都计算出来 import collectio ...

  4. ubuntu安装markdown

    # sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE linuxidc@linuxidc:~ ...

  5. mysql数据库优化的几种方法

    1.选取最适用的字段属性 MySQL可以很好的支持大数据量的存取,但是一般说来,数据库中的表越小,在它上面执行的查询也就会越快.因此,在创建表的时候,为了获得更好的性能,我们可以将表中字段的宽度设得尽 ...

  6. 取得选中Grid的数据

    var MergeAction = new Ext.Action({ text: '合并(选中两行)', handler: function () { if (grid.getSelectionMod ...

  7. css-1,css的三种引入方式 基本选择器

    <!-- (1)CSS 层叠样式表 作用:修饰网页结构 (2)css的三种引入方式 权重: 优先级高 权重大 谁在页面谁的权重大 - 行内样式 注意:行内样式的优先级是最高的 - 内接样式 - ...

  8. hdu4300 Clairewd’s message

    地址:http://acm.hdu.edu.cn/showproblem.php?pid=4300 题目: Clairewd’s message Time Limit: 2000/1000 MS (J ...

  9. Winter-1-C A + B II 解题报告及测试数据

    Time Limit:1000MS Memory Limit:32768KB Description I have a very simple problem for you. Given two i ...

  10. spark 作业提交

    kafka-topics.sh --describe --zookeeper xxxxx:2181 --topic testkafka-run-class.sh kafka.tools.GetOffs ...