- 浏览: 1427293 次
文章分类
最新评论
-
学习的小麦:
博主是个大好人,求求你了1169293832我QQ,先谢博主
局域网控制(二)——控制客户端 -
学习的小麦:
博主,由于毕业设计的需要,可以请求博主给完整程序给我吗?
局域网控制(二)——控制客户端 -
netkongjian:
不错CAD控件知识,感谢分享[deyi]
适合任何CAD版本的CAD开发技巧 -
wangguxian:
它的起点是没有算在里面的,所以第一个点的返回值是-1,其他的都 ...
和大家分享一个判断点是否在多边形范围内的算法 -
xchyou:
ECMAScript
WCF的用户名+密码认证方式
概述
今天在做Master Data Service(后面简称MDS)项目时需要通过WCF来使用MDS的API,从而对MDS的数据进行操作。在这个过程中,遇到了一个棘手的问题,就是在客户端调用Web Service时的身份认证问题,于是乎对WCF的认证方式做了一个简单的了解。在这里还要感谢蔡总陪我加班一起解决问题,在蔡总的大力支持下问题得以解决。我们解决问题的方式采用了客户端用户名+密码的方式来进行身份认证,这只是诸多WCF认证方式当中的一种。
用户名+密码认证的三种模式
基于用户名/密码的用户凭证通过类型UserNamePasswordClientCredential表示。而在ClientCredentials中,只读属性UserName表示这样一个用户凭证。可以按照Windows凭证的方式为ChannelFactory<TChannel>或者ClientBase<TChannel>基于用户名/密码凭证。
- publicclassClientCredentials
- {
- //其他成员
- publicUserNamePasswordClientCredentialUserName{get;}
- }
- publicsealedclassUserNamePasswordClientCredential
- {
- //其他成员
- publicstringPassword{get;set;}
- publicstringUserName{get;set;}
- }
用户名/密码凭证在客户端的设置很容易,但是我们关心的是服务端采用怎样的机制来验证这个凭证。WCF提供了如下三种方式来验证凭证中用户名是否和密码相符:
- Windows:将用户名和密码映射为Windows帐号和密码,采用Windows认证;
- MembershipProvider:利用配置的MembershipProvider验证用户名和密码;
- 自定义:通过继承抽象类UsernamePasswordValidator,自定义用户名/密码验证器进行验证。
WCF通过枚举UserNamePasswordValidationMode定了上述三种用户名/密码认证模式。该枚举定义如下,其中Windows是默认选项。
- publicenumUserNamePasswordValidationMode
- {
- Windows,
- MembershipProvider,
- Custom
- }
上述三种认证模式的设置最终通过之前提到过的ServiceCredentials这一服务行为进行设置的。从下面的定义我们可以看出,ServiceCredentials定义了只读属性UserNameAuthentication用于基于用户名/密码认证的相关设置。属性的类型为UserNamePasswordServiceCredential,定义其中的UserNamePasswordValidationMode属性表示采用的认证模式。如果选择了需要通过属性MembershipProvider设置采用的MembershipProvider。如果选择了Custom,则需要通过CustomUserNamePasswordValidator属性指定你自定义的UserNamePasswordValidator对象。
- publicclassServiceCredentials:SecurityCredentialsManager,IServiceBehavior
- {
- //其他成员
- publicUserNamePasswordServiceCredentialUserNameAuthentication{get;}
- }
- publicsealedclassUserNamePasswordServiceCredential
- {
- //其他成员
- publicUserNamePasswordValidatorCustomUserNamePasswordValidator{get;set;}
- publicMembershipProviderMembershipProvider{get;set;}
- publicUserNamePasswordValidationModeUserNamePasswordValidationMode{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。
- INSERTINTO[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中。
- <?xmlversion="1.0"?>
- <configuration>
- <connectionStrings>
- <addname="AspNetDb"connectionString="Server=.;Database=AspNetDb;Uid=sa;Pwd=password"/>
- </connectionStrings>
- <system.web>
- <membershipdefaultProvider="myProvider">
- <providers>
- <addname="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>
- <bindingname="userNameCredentialBinding">
- <securitymode="Message">
- <messageclientCredentialType="UserName"/>
- </security>
- </binding>
- </ws2007HttpBinding>
- </bindings>
- <services>
- <servicename="Artech.WcfServices.Services.CalculatorService"behaviorConfiguration="membershipAuthentication">
- <endpointaddress="http://127.0.0.1/calculatorservice"binding="ws2007HttpBinding"
- bindingConfiguration="userNameCredentialBinding"contract="Artech.WcfServices.Contracts.ICalculator"/>
- </service>
- </services>
- <behaviors>
- <serviceBehaviors>
- <behaviorname="membershipAuthentication">
- <serviceCredentials>
- <serviceCertificatestoreLocation="LocalMachine"storeName="My"x509FindType="FindBySubjectName"findValue="YueXu-PC"/>
- <userNameAuthenticationuserNamePasswordValidationMode="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(ServiceHosthost=newServiceHost(typeof(CalculatorService)))
- {
- host.Open();
- Console.Read();
- }
接下来我们需要对客户端的配置进行相应的调整,整个配置内容如下面的XML片断所示。对于这段配置有一点需要注意的是:终结点应用了一个名称为peerTrustSvcCertValidation的行为,该行为中将服务证书认证模式设置成PeerTrust,所以你需要通过MMC证书管理单元的导出/导入功能将YueXu-PC证书导入到“受信任人(Trusted People)”存储区。
- <?xmlversion="1.0"?>
- <configuration>
- <system.serviceModel>
- <bindings>
- <ws2007HttpBinding>
- <bindingname="userNameCredentialBinding">
- <securitymode="Message">
- <messageclientCredentialType="UserName"/>
- </security>
- </binding>
- </ws2007HttpBinding>
- </bindings>
- <client>
- <endpointname="calculatorService"behaviorConfiguration="peerTrustSvcCertValidation"
- address=<ahref="http://127.0.0.1/calculatorservice">http://127.0.0.1/calculatorservice</a>binding="ws2007HttpBinding"
- bindingConfiguration="userNameCredentialBinding"contract="Artech.WcfServices.Contracts.ICalculator">
- <identity>
- <certificateReferencestoreLocation="LocalMachine"storeName="My"x509FindType="FindBySubjectName"findValue="YueXu-PC"/>
- </identity>
- </endpoint>
- </client>
- <behaviors>
- <endpointBehaviors>
- <behaviorname="peerTrustSvcCertValidation">
- <clientCredentials>
- <serviceCertificate>
- <authenticationcertificateValidationMode="PeerTrust"/>
- </serviceCertificate>
- </clientCredentials>
- </behavior>
- </endpointBehaviors>
- </behaviors>
- </system.serviceModel>
- </configuration>
最后,我们来编写如下一段客户端进行服务调用的程序。在下面的代码中,我进行了两次服务调用。但是创建服务代理对象的ChannelFactory<ICalculator>被设置了不同的用户名凭证。其中第一个是正确的用户名和密码,后一个却指定了一个根本不存在的用户名。
- using(ChannelFactory<ICalculator>channelFactory=newChannelFactory<ICalculator>("calculatorService"))
- {
- UserNamePasswordClientCredentialcredential=channelFactory.Credentials.UserName;
- credential.UserName="xuyue";
- credential.Password="password01";
- ICalculatorcalculator=channelFactory.CreateChannel();
- calculator.Add(1,2);
- Console.WriteLine("服务调用成功...");
- }
- using(ChannelFactory<ICalculator>channelFactory=newChannelFactory<ICalculator>("calculatorService"))
- {
- UserNamePasswordClientCredentialcredential=channelFactory.Credentials.UserName;
- credential.UserName="wrongName";
- credential.Password="wrongPWD";
- ICalculatorcalculator=channelFactory.CreateChannel();
- try
- {
- calculator.Add(1,2);
- }
- catch
- {
- Console.WriteLine("服务调用失败...");
- }
- }
输出结果:
1: 服务调用成功...
2: 服务调用失败...
概述
今天在做Master Data Service(后面简称MDS)项目时需要通过WCF来使用MDS的API,从而对MDS的数据进行操作。在这个过程中,遇到了一个棘手的问题,就是在客户端调用Web Service时的身份认证问题,于是乎对WCF的认证方式做了一个简单的了解。在这里还要感谢蔡总陪我加班一起解决问题,在蔡总的大力支持下问题得以解决。我们解决问题的方式采用了客户端用户名+密码的方式来进行身份认证,这只是诸多WCF认证方式当中的一种。
用户名+密码认证的三种模式
基于用户名/密码的用户凭证通过类型UserNamePasswordClientCredential表示。而在ClientCredentials中,只读属性UserName表示这样一个用户凭证。可以按照Windows凭证的方式为ChannelFactory<TChannel>或者ClientBase<TChannel>基于用户名/密码凭证。
- publicclassClientCredentials
- {
- //其他成员
- publicUserNamePasswordClientCredentialUserName{get;}
- }
- publicsealedclassUserNamePasswordClientCredential
- {
- //其他成员
- publicstringPassword{get;set;}
- publicstringUserName{get;set;}
- }
用户名/密码凭证在客户端的设置很容易,但是我们关心的是服务端采用怎样的机制来验证这个凭证。WCF提供了如下三种方式来验证凭证中用户名是否和密码相符:
- Windows:将用户名和密码映射为Windows帐号和密码,采用Windows认证;
- MembershipProvider:利用配置的MembershipProvider验证用户名和密码;
- 自定义:通过继承抽象类UsernamePasswordValidator,自定义用户名/密码验证器进行验证。
WCF通过枚举UserNamePasswordValidationMode定了上述三种用户名/密码认证模式。该枚举定义如下,其中Windows是默认选项。
- publicenumUserNamePasswordValidationMode
- {
- Windows,
- MembershipProvider,
- Custom
- }
上述三种认证模式的设置最终通过之前提到过的ServiceCredentials这一服务行为进行设置的。从下面的定义我们可以看出,ServiceCredentials定义了只读属性UserNameAuthentication用于基于用户名/密码认证的相关设置。属性的类型为UserNamePasswordServiceCredential,定义其中的UserNamePasswordValidationMode属性表示采用的认证模式。如果选择了需要通过属性MembershipProvider设置采用的MembershipProvider。如果选择了Custom,则需要通过CustomUserNamePasswordValidator属性指定你自定义的UserNamePasswordValidator对象。
- publicclassServiceCredentials:SecurityCredentialsManager,IServiceBehavior
- {
- //其他成员
- publicUserNamePasswordServiceCredentialUserNameAuthentication{get;}
- }
- publicsealedclassUserNamePasswordServiceCredential
- {
- //其他成员
- publicUserNamePasswordValidatorCustomUserNamePasswordValidator{get;set;}
- publicMembershipProviderMembershipProvider{get;set;}
- publicUserNamePasswordValidationModeUserNamePasswordValidationMode{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。
- INSERTINTO[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中。
- <?xmlversion="1.0"?>
- <configuration>
- <connectionStrings>
- <addname="AspNetDb"connectionString="Server=.;Database=AspNetDb;Uid=sa;Pwd=password"/>
- </connectionStrings>
- <system.web>
- <membershipdefaultProvider="myProvider">
- <providers>
- <addname="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>
- <bindingname="userNameCredentialBinding">
- <securitymode="Message">
- <messageclientCredentialType="UserName"/>
- </security>
- </binding>
- </ws2007HttpBinding>
- </bindings>
- <services>
- <servicename="Artech.WcfServices.Services.CalculatorService"behaviorConfiguration="membershipAuthentication">
- <endpointaddress="http://127.0.0.1/calculatorservice"binding="ws2007HttpBinding"
- bindingConfiguration="userNameCredentialBinding"contract="Artech.WcfServices.Contracts.ICalculator"/>
- </service>
- </services>
- <behaviors>
- <serviceBehaviors>
- <behaviorname="membershipAuthentication">
- <serviceCredentials>
- <serviceCertificatestoreLocation="LocalMachine"storeName="My"x509FindType="FindBySubjectName"findValue="YueXu-PC"/>
- <userNameAuthenticationuserNamePasswordValidationMode="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(ServiceHosthost=newServiceHost(typeof(CalculatorService)))
- {
- host.Open();
- Console.Read();
- }
接下来我们需要对客户端的配置进行相应的调整,整个配置内容如下面的XML片断所示。对于这段配置有一点需要注意的是:终结点应用了一个名称为peerTrustSvcCertValidation的行为,该行为中将服务证书认证模式设置成PeerTrust,所以你需要通过MMC证书管理单元的导出/导入功能将YueXu-PC证书导入到“受信任人(Trusted People)”存储区。
- <?xmlversion="1.0"?>
- <configuration>
- <system.serviceModel>
- <bindings>
- <ws2007HttpBinding>
- <bindingname="userNameCredentialBinding">
- <securitymode="Message">
- <messageclientCredentialType="UserName"/>
- </security>
- </binding>
- </ws2007HttpBinding>
- </bindings>
- <client>
- <endpointname="calculatorService"behaviorConfiguration="peerTrustSvcCertValidation"
- address=<ahref="http://127.0.0.1/calculatorservice">http://127.0.0.1/calculatorservice</a>binding="ws2007HttpBinding"
- bindingConfiguration="userNameCredentialBinding"contract="Artech.WcfServices.Contracts.ICalculator">
- <identity>
- <certificateReferencestoreLocation="LocalMachine"storeName="My"x509FindType="FindBySubjectName"findValue="YueXu-PC"/>
- </identity>
- </endpoint>
- </client>
- <behaviors>
- <endpointBehaviors>
- <behaviorname="peerTrustSvcCertValidation">
- <clientCredentials>
- <serviceCertificate>
- <authenticationcertificateValidationMode="PeerTrust"/>
- </serviceCertificate>
- </clientCredentials>
- </behavior>
- </endpointBehaviors>
- </behaviors>
- </system.serviceModel>
- </configuration>
最后,我们来编写如下一段客户端进行服务调用的程序。在下面的代码中,我进行了两次服务调用。但是创建服务代理对象的ChannelFactory<ICalculator>被设置了不同的用户名凭证。其中第一个是正确的用户名和密码,后一个却指定了一个根本不存在的用户名。
- using(ChannelFactory<ICalculator>channelFactory=newChannelFactory<ICalculator>("calculatorService"))
- {
- UserNamePasswordClientCredentialcredential=channelFactory.Credentials.UserName;
- credential.UserName="xuyue";
- credential.Password="password01";
- ICalculatorcalculator=channelFactory.CreateChannel();
- calculator.Add(1,2);
- Console.WriteLine("服务调用成功...");
- }
- using(ChannelFactory<ICalculator>channelFactory=newChannelFactory<ICalculator>("calculatorService"))
- {
- UserNamePasswordClientCredentialcredential=channelFactory.Credentials.UserName;
- credential.UserName="wrongName";
- credential.Password="wrongPWD";
- ICalculatorcalculator=channelFactory.CreateChannel();
- try
- {
- calculator.Add(1,2);
- }
- catch
- {
- Console.WriteLine("服务调用失败...");
- }
- }
输出结果:
1: 服务调用成功...
2: 服务调用失败...
相关推荐
WCF用户名密码验证Demo,含证书相关代码,适合初学者学习WCF服务的调用安全配置。
WCF加密传输数据,b并且用户名+密码验证,参看文章https://www.cnblogs.com/birds-zhu/p/10565604.html
wcf,用户名,密码,验证,wcf安全,
一直不明白如何验证RESTFul风格的交互安全,搞了好几天,终于找到了两个源码,分享给大家,希望对大家有帮助 。
DevExpress+WindowsService+WCF+EF+SQL 一体化搭建起来的框架,调试编译成功后,使用installutil.exe安装windows服务。
.NET企业级WCF演示+源代码(全)(经典)
一个学习WCF+LINQ+WPF很好的一个范例
教程可见http://www.cnblogs.com/lbhqq/p/6830875.html
EF+WCF+WPF(MVVM)框架简单示例
蒋金楠老师的wcf教程,个人看了,觉得写的很不错,对刚入门和深入了解wcf都适用,有需要的同学可下载学习
消息安全模式之...也就是客户端提供用户名和密码才可以访问此服务。 1.身份验证(服务器):提供证书,(使用 HTTP)用于初始会话协商和证明服务身份。 2.身份验证(客户端):客户端使用用户名和密码进行身份验证
1、Silverlight WCF服务 Chart画图 StackedColumn 堆积柱形图 Column 柱形图 Pie 饼图 Line 拆线图 2、利用SLVisifire.Charts.dll,后台直接动态生成StackedColumn、Column、Pie、Line,几个实例都在一个页面,其中...
WCF+Asp.net WCF+Asp.net WCF+Asp.net WCF+Asp.net WCF+Asp.net
WCF WEB WPF WinFrom承载
asp.net+wcf+entity framework
WCF+Winfrom,wcf利用网站承载服务,winform访问wcf获取数据,全套系统模块功能
金旭亮WCF课程系列之WCF概述金旭亮WCF课程系列之WCF概述金旭亮WCF课程系列之WCF概述金旭亮WCF课程系列之WCF概述金旭亮WCF课程系列之WCF概述
silverlight调用wcf服务,silverlight的承载页为独立的web网站,silverlight、wcf服务共享model的对象。
WCF+WF+SilverLight培训实例
适合刚刚学习WCF+winform的朋友门,很基础的例子,也很容易上手。