WCF的用户名+密码认证方式

概述

今天在做Master Data Service(后面简称MDS)项目时需要通过WCF来使用MDS的API,从而对MDS的数据进行操作。在这个过程中,遇到了一个棘手的问题,就是在客户端调用Web Service时的身份认证问题,于是乎对WCF的认证方式做了一个简单的了解。在这里还要感谢蔡总陪我加班一起解决问题,在蔡总的大力支持下问题得以解决。我们解决问题的方式采用了客户端用户名+密码的方式来进行身份认证,这只是诸多WCF认证方式当中的一种。

用户名+密码认证的三种模式

基于用户名/密码的用户凭证通过类型UserNamePasswordClientCredential表示。而在ClientCredentials中,只读属性UserName表示这样一个用户凭证。可以按照Windows凭证的方式为ChannelFactory<TChannel>或者ClientBase<TChannel>基于用户名/密码凭证。

public class ClientCredentials
{//其他成员public UserNamePasswordClientCredential UserName { get; }
} 
public sealed class UserNamePasswordClientCredential
{//其他成员public string Password {get; set; }public string UserName { get; set; }
}

用户名/密码凭证在客户端的设置很容易,但是我们关心的是服务端采用怎样的机制来验证这个凭证。WCF提供了如下三种方式来验证凭证中用户名是否和密码相符:

  • Windows:将用户名和密码映射为Windows帐号和密码,采用Windows认证;
  • MembershipProvider:利用配置的MembershipProvider验证用户名和密码;
  • 自定义:通过继承抽象类UsernamePasswordValidator,自定义用户名/密码验证器进行验证。

WCF通过枚举UserNamePasswordValidationMode定了上述三种用户名/密码认证模式。该枚举定义如下,其中Windows是默认选项。

public enum UserNamePasswordValidationMode
{Windows,MembershipProvider,Custom
}

上述三种认证模式的设置最终通过之前提到过的ServiceCredentials这一服务行为进行设置的。从下面的定义我们可以看出,ServiceCredentials定义了只读属性UserNameAuthentication用于基于用户名/密码认证的相关设置。属性的类型为UserNamePasswordServiceCredential,定义其中的UserNamePasswordValidationMode属性表示采用的认证模式。如果选择了需要通过属性MembershipProvider设置采用的MembershipProvider。如果选择了Custom,则需要通过CustomUserNamePasswordValidator属性指定你自定义的UserNamePasswordValidator对象。

public class ServiceCredentials: SecurityCredentialsManager, IServiceBehavior
{//其他成员public UserNamePasswordServiceCredential UserNameAuthentication { get; }
}
public sealed class UserNamePasswordServiceCredential
{//其他成员public UserNamePasswordValidator CustomUserNamePasswordValidator { get; set; }public MembershipProvider MembershipProvider { get; set; }public UserNamePasswordValidationMode UserNamePasswordValidationMode { get; set;}

通过MembershipProvider进行用户名+密码的认证

Membership是ASP.NET中一个重要的模块,旨在进行基于用户名/密码的认证和对应的帐号管理。Membership采用策略设计模式,所有的API通过几个静态Membership类暴露出来,而相应的功能实现在具体的Membership提供者中。所有的提供者继承自同一个抽象类MembershipProvider。ASP.NET提供了两种类型的提供者:SqlMembershipProvider和ActiveDirectoryMembershipProvider。前者将用户存储于SQL Server数据库中,而后者则直接建立在AD之上,本实例采用SqlMembershipProvider,在前面一个实例演示中,我们创建了以计算服务为场景的解决方案,现在我们直接沿用它。
首要的任务是在用于存储帐户信息的SQL Server数据库,为此可以先在本地SQL Server创建一个空的数据库(假设起名为AspNetDb)。接着需要在该数据库中创建SqlMembershipProvider所需的数据表和相应的存储过程。这些数据库对象的创建,需要借助aspnet_regsql.exe这个工具。你只需要以命令行的方式执行如下aspnet_regsql.exe(无需任何参数),相应的向导就会出现。
在向导弹出的前两个窗体中保持默认设置,直接点击“下一步”后,会出现一个数据库选择窗体。此时你需要选择我们刚刚创建的数据库,点击“确认”后,相关的数据库对象会为你创建出来。
这些创建出来的数据表可以同时服务于多个应用,所有每一个表中都具有一个名称为ApplicationId的字段来明确该条记录对应的应用。而所有应用记录维护在aspnet_Applications这么一个表中。现在需要通过执行下面一段SQL脚本在该表中添加一条表示应用的记录。将其命名为MembershipAuthenticationDemo。

INSERT INTO [aspnet_Applications]([ApplicationName],[LoweredApplicationName],[ApplicationId],[Description])
VALUES('MembershipAuthenticationDemo','membershipauthenticationdemo',NEWID(),'')

现在数据库方面已经准备就绪,接着来完成编程和配置方面的工作。不打算从新创建一个解决方案,而是直接对之前演示的实例进行改造。我们采用自我寄宿的方式,由于Membership隶属于ASP.NET,所以需要添加System.Web.dll的引用,如果采用的是.NET Frameowrk 4.0(本例所示的配置也是基于该版本),则还需额外添加对System.Web.ApplicationServices.dll的引用。接下来,需要在服务寄宿方面所做的工作就是将下面一段配置整个拷贝到app.config中。

<?xml version="1.0"?>
<configuration><connectionStrings><add name="AspNetDb" connectionString="Server=.; Database=AspNetDb; Uid=sa; Pwd=password"/></connectionStrings><system.web><membership defaultProvider="myProvider"><providers><add name="myProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=4.0.0.0, Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="AspNetDb" applicationName="MembershipAuthenticationDemo"
requiresQuestionAndAnswer="false"/></providers></membership></system.web><system.serviceModel><bindings><ws2007HttpBinding><binding name="userNameCredentialBinding"><security mode="Message"><message clientCredentialType="UserName"/></security></binding></ws2007HttpBinding></bindings><services><service name="Artech.WcfServices.Services.CalculatorService" behaviorConfiguration="membershipAuthentication"><endpoint address="http://127.0.0.1/calculatorservice" binding="ws2007HttpBinding"
bindingConfiguration="userNameCredentialBinding" contract="Artech.WcfServices.Contracts.ICalculator"/></service></services><behaviors><serviceBehaviors><behavior  name="membershipAuthentication"><serviceCredentials><serviceCertificate storeLocation="LocalMachine" storeName ="My" x509FindType="FindBySubjectName" findValue="YueXu-PC"/><userNameAuthentication userNamePasswordValidationMode="MembershipProvider" membershipProviderName="myProvider"/></serviceCredentials></behavior></serviceBehaviors></behaviors></system.serviceModel>
</configuration>

至此,在我们创建的数据库中并没有用户帐户记录。为了演示认证效果,我们需要创建相关用户帐户记录。为了方便,我直接将相关的代码写在了服务寄宿的代码中。如下面的代码片断所示,在对服务进行寄宿之前,我通过调用Membership的静态方法CreateUser创建了一个用户名、密码和Email分别为xuyue、password01和xuyue1000@hotmail的帐号。

if (Membership.FindUsersByName("xuyue").Count == 0)
{Membership.CreateUser("xuyue", "password01", "xuyue1000@hotmail.com");
}
using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
{host.Open();Console.Read();
}

接下来我们需要对客户端的配置进行相应的调整,整个配置内容如下面的XML片断所示。对于这段配置有一点需要注意的是:终结点应用了一个名称为peerTrustSvcCertValidation的行为,该行为中将服务证书认证模式设置成PeerTrust,所以你需要通过MMC证书管理单元的导出/导入功能将YueXu-PC证书导入到“受信任人(Trusted People)”存储区。

<?xml version="1.0"?>
<configuration><system.serviceModel><bindings><ws2007HttpBinding><binding name="userNameCredentialBinding"><security mode="Message"><message clientCredentialType="UserName"/></security></binding></ws2007HttpBinding></bindings><client><endpoint name="calculatorService" behaviorConfiguration="peerTrustSvcCertValidation"
address=http://127.0.0.1/calculatorservice binding="ws2007HttpBinding"
bindingConfiguration="userNameCredentialBinding" contract="Artech.WcfServices.Contracts.ICalculator"><identity><certificateReference storeLocation="LocalMachine" storeName ="My" x509FindType="FindBySubjectName" findValue="YueXu-PC"/></identity></endpoint></client><behaviors><endpointBehaviors><behavior name="peerTrustSvcCertValidation"><clientCredentials><serviceCertificate><authentication certificateValidationMode="PeerTrust"/></serviceCertificate></clientCredentials></behavior></endpointBehaviors></behaviors></system.serviceModel>
</configuration>

最后,我们来编写如下一段客户端进行服务调用的程序。在下面的代码中,我进行了两次服务调用。但是创建服务代理对象的ChannelFactory<ICalculator>被设置了不同的用户名凭证。其中第一个是正确的用户名和密码,后一个却指定了一个根本不存在的用户名。

using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
{UserNamePasswordClientCredential credential = channelFactory.Credentials.UserName;credential.UserName     = "xuyue";credential.Password     = "password01";ICalculator calculator  = channelFactory.CreateChannel();calculator.Add(1, 2);Console.WriteLine("服务调用成功...");
}
using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>("calculatorService"))
{UserNamePasswordClientCredential credential = channelFactory.Credentials.UserName;credential.UserName     = "wrongName";credential.Password     = "wrongPWD";ICalculator calculator  = channelFactory.CreateChannel();try{calculator.Add(1, 2);}catch{Console.WriteLine("服务调用失败...");}
}

输出结果:

1: 服务调用成功...

2: 服务调用失败...

转载于:https://www.cnblogs.com/hainange/archive/2011/08/02/6153588.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/303403.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

lmbs PHP,PHP 清空 MySql 指定数据表中的所有数据

PHP 清空 MySql 指定数据表中的所有数据PHP 清空 MySql 指定数据表中的所有数据&#xff0c;在烈火小编在网上闲逛时&#xff0c;这是某技术博客的一篇文章&#xff0c;说是文章&#xff0c;并没有文字&#xff0c;只有代码&#xff0c;经过测试可以使用&#xff0c;现在分享给…

全网最通透的“闭包”认知 · 跨越语言

闭包作为前端面试的必考题目&#xff0c;常让1-3年工作经验的JavaScripter感到困惑&#xff0c;其实主流语言都有闭包。今天我们深入聊一聊[闭包]&#xff0c; 查缺补漏&#xff01;1. 以面试题 投石问路 2. 以C#闭包 庖丁解牛 3. 跨越语言 追本溯源 • 头等函数 •…

北大最神博士论文:为什么学校打印店老板大多是湖南人?

导读&#xff1a;北京大学社会学系博士冯军旗的一篇论文&#xff0c;虽然是话题看起来有些奇葩&#xff0c;但仍然考据严谨&#xff0c;很有价值。01 写在前面&#xff08;非论文部分&#xff09;多媒体出版行业中&#xff0c;充满油墨芬芳的印刷总是长盛不衰。特别是在大学校园…

php 谷歌语音,php 语音参考

如果文件内容是纯 PHP 代码&#xff0c;最好在文件末尾删除 PHP 结束标记。这可以避免在 PHP 结束标记之后万一意外加入了空格或者换行符&#xff0c;会导致 PHP 开始输出这些空白&#xff0c;而脚本中此时并无输出的意图。 /* This is a multi line commentyet another line …

技术分享 | jaeger链路日志实现

源宝导读&#xff1a;随着企业应用越来越复杂&#xff0c;内部的调用链条越来越长&#xff0c;性能问题也变得越来越难以定位和排查&#xff0c;为了应对此问题&#xff0c;我们在移动平台中引入了“jaeger调用链追踪工具”&#xff0c;帮助我们高效定位云端服务的性能问题。本…

IT资料,重磅来袭!

现在IT行业越来越火爆&#xff0c;技术的更新也越来越快&#xff0c;不好好充实自己的话&#xff0c;就会被淘汰。小编这几年一直有意识地收集IT行业相关的资料&#xff0c;现在已经拥有8G左右的资料&#xff0c;如区块链、Python、大数据、人工智能深度学习等方面的资料&#…

开启php的文件上传扩展,linux中如何通过php.ini添加扩展?

在编译安装的时候&#xff0c;我只通过了以下命令来安装&#xff0c;然后我想像windows中那样修改 php.ini 就开启了扩展./configure \--enable-fpm \--with-fpm-userwww-data \--with-fpm-groupwww-data \--enable-soap \--enable-mysqlnd \--with-mysqlimysqlnd \--with-pdo-…

[C#.NET 拾遗补漏]16:几个常见的TAP异步操作

在本系列上一篇文章 [15&#xff1a;异步编程基础] 中&#xff0c;我们讲到&#xff0c;现代应用程序广泛使用的是基于任务的异步编程模式&#xff08;TAP&#xff09;&#xff0c;历史的 EAP 和 AMP 模式已经过时不推荐使用。今天继续总结一下 TAP 的异步操作&#xff0c;比如…

荐书 | 10本书给你计算机大师思维

《黑客与画家》作者&#xff1a;保罗格雷厄姆 / 译者&#xff1a;阮一峰美国互联网界如日中天的教父、哈佛大学离经叛道的博士保罗格雷厄姆著作&#xff01;一本书&#xff0c;你不曾想到的视角&#xff0c;彻底颠覆你对世界的认识&#xff01;美国亚马逊、纽约时报超级畅销书&…

如何解决U盘无法停止通用卷设备

当我们使用完U盘&#xff0c;在电脑上安全删除时&#xff0c;电脑却提示&#xff1a;无法停止‘通用卷设备。这是什么问题呢&#xff1f;这时候不要硬拔哦&#xff0c;因为硬拔可能会损坏我们U盘的资料文件或者电脑的USB接口。正确的解决方法&#xff1a; 第一种&#xff1a; 往…

php按时间分组的sql语句,(SQL语句)按指定时间段分组统计

---------------------------------------Author : liangCK 梁爱兰--Comment: 小梁 爱 兰儿--Date : 2010-01-02 16:47:10---------------------------------------> 生成测试数据: #tbCREATETABLE#tb(列名1varchar(12),时间datetime)INSERTINTO#tbSELECT03174190188,2009…

NET问答: 说说你对 LookupTKey, TElement 的看法 ?

咨询区 dan-gph&#xff1a;MSND 上对 Lookup 做了如下的解释。Lookup<TKey, TElement> 类似于 Dictionary<TKey,TValue>, 不同点在于 Dictionary<TKey, TValue> 中的key对应的是单个value&#xff0c;而 Lookup<TKey, TElement> 中的 key 对应的是一个…

最多金的编程语言Top10:Python第3,R第10,你猜第1是谁?

导读&#xff1a;如果你还在纠结选哪门编程语言来开启你的码农生涯&#xff0c;这将是你的最佳指南。本文绝非标题党&#xff0c;而是基于大量数据和为期两周的深入探究&#xff0c;在18年初&#xff0c;对IT行业的现状、趋势以及预测进行客观观察&#xff0c;让大家对编程语言…

[转贴]制作windows 2003自动安装盘-集成补丁/Raid及硬件驱动

从事网游行业的工作人员&#xff0c;如果一款游戏上线&#xff0c;必须上大量服务器。用品牌机引导盘装系统&#xff0c;再打个补丁&#xff0c;速度真让人不敢恭维。为了提高效率&#xff0c;就尝试制作一张集成系统补丁/RAID及硬件驱动自动安windows 2003系统盘。下面以品牌机…

4月 .NET 线上 Meetup,快来报名

点击蓝字关注我们.NET 6 preview 2 在3月11日已经发布&#xff0c;.NET 6 将是 .NET Core 3.1 之后的第一个 LTS 版本&#xff0c;也是微软开启全平台统一一个 .NET 计划以来的第一个 LTS 版本&#xff0c;意义不可谓不大&#xff0c;那么 .NET 5/6 又会带来哪些新特性呢&#…

NP完全性理论与近似算法

一、图灵机根据有限状态控制器的当前状态及每个读写头读到的带符号&#xff0c;图灵机的一个计算步可实现下面3个操作之一或全部。改变有限状态控制器中的状态。清除当前读写头下的方格中原有带符号并写上新的带符号。独立地将任何一个或所有读写头&#xff0c;向左移动一个方格…

php文件上传实验总结,53 PHP文件处理(六)文件上传--总结---细说php

前台表单设计,表单view.html,提交给upload.php一.表单view.htmlphp配置文件和上传文件有关选项&#xff0c;注意几点:php.inifile_uploadsonupload_max_filesize2M 此值最大不超过服务器内存upload_tmp_dirc:/uploads 到时要拷贝出来post_max_size25M 要大于upload_max_fil…

CentOS 5.6 快速搭建LAMP

在虚拟机下安装了个CentOS&#xff0c;5.6版本的。利用NAT模式与宿主pc共享上网&#xff01; 当然可以采用编译源码的方式搭建lamp。这里只是介绍快速搭建php开发框架的方法。其实也没什么&#xff0c;主要是是是使用linux的yum来在线安装。如果上不了网请查找编译lamp的文…

阿里25k 百度25k,招WPF!

.NET5打通7大开发方向&#xff0c;CLR超高性能&#xff0c;.NET6支持Blazor嵌入WPF&#xff0c;还有MAUI跨平台UI解决方案&#xff0c;都是.NET的利好&#xff0c;也是WPF的利好。牛年跳槽季&#xff0c;.NET在客户端方向一骑绝尘&#xff0c;阿里影视、百度地图&#xff0c;以…

php转译html,使用php转义输出HTML到JavaScript

最近在做天地图是GIS集成要输出HTML到JavaScript里面涉及到代码转义什么的比较麻烦所以写个PHP的function分享一下&#xff1a;function jsformat($str){$str trim($str);$str str_replace(\\s\\s, \\s, $str);$str str_replace(chr(10), , $str);$str str_replace(chr(13)…