实现分布式的Membership和上下文传递.docx
- 文档编号:23889234
- 上传时间:2023-05-21
- 格式:DOCX
- 页数:23
- 大小:22.20KB
实现分布式的Membership和上下文传递.docx
《实现分布式的Membership和上下文传递.docx》由会员分享,可在线阅读,更多相关《实现分布式的Membership和上下文传递.docx(23页珍藏版)》请在冰豆网上搜索。
实现分布式的Membership和上下文传递
实现分布式的Membership和上下文传递
通过上一篇了解了模块内基本的层次划分之后,接下来我们来聊聊PetShop中一些基本基础功能的实现,以及一些设计、架构上的应用如何同WCF进行集成。
本篇讨论两个问题:
实现分布式的Membership和客户端到服务端上下文(Context)的传递。
一、如何实现用户验证
对登录用户的验证是大部分应用所必需的,对于ASP.NET来说,用户验证及帐号管理实现在成员资格(Membership)模块中。
同ASP.NET的其他模块一样,微软在设计Membership的时候,为了实现更好地可扩展性,采用了策略(Strategy)设计模式:
将模块相关的功能定义在被称为Provider的抽象类型中,并通过继承它提供具体的Provider。
如果这些原生的Provider不能满足你的需求,你也可以通过继承该抽象的Provider,创建自定义的Provider。
通过ASP.NET提供的配置,你可以很轻易地把自定义的Provider应用到你的应用之中。
在一般情况下,最终的编程人员并不通过Provider调用相关的功能,而是通过一个外观(Facade)类实现对相关功能的调用。
ASP.NET成员资格模块的设计基本上可以通过下面的类图1反映出来:
最终的编程人员通过外观类型(FaçadeClass)Membership调用成员资格相关的功能,比如用户认证、用户注册、修改密码等;Membership通过抽象类MembershipProvider提供所有的功能,至于最终的实现,则定义在一个个具体的MembershipProvider中。
基于成员资格信息不同的存储方式,ASP.NET提供了两个原生的MembershipProvider:
SqlMembershipProvider和ActiveDirectoryMembershipProvider,前者基于SQLServer数据库,后者基于AD。
如果这两个MembershipProvider均不能满足需求,我们还可以自定义MembershipProvider。
clip_image002
图1ASP.NETMembership设计原理
我们的案例并不会部署于AD之中,所以不能使用ActiveDirectoryMembershipProvider;直接通过Web服务器进行数据库的存取又不符合上述物理部署的要求(通过应用服务器进行数据库访问),所以SqlMembershipProvider也不能为我们所用。
为此需要自定义MembershipProvider,通过WCF服务调用的形式提供成员资格所有功能的实现。
我们将该自定义MembershipProvider称为RemoteMembershipProvider。
图2揭示了RemoteMembershipProvider实现的原理:
RemoteMembershipProvider通过调用WCF服务MembershipService提供对成员资格所有功能的实现;MembershipService则通过调用Membership实现服务;最终的实现还是落在了SqlMembershipProvider这个原生的MembershipProvider上。
clip_image004
图2RemoteMembershipProvider实现原理
1、服务契约和服务实现
首先来看看MembershipService实现的服务契约的定义。
由于MembershipService最终是为RemoteMembershipProvider这个自定义MembershipProvider服务的,所以服务操作的定义是基于MembershipProvider的API定义。
MembershipProvider包含两种类型的成员:
属性和方法,简单起见,我们可以为MembershipProvider每一个抽象方法定义一个匹配的服务操作;而对于所有属性,完全采用服务端(应用服务器)的MembershipProvider相关属性。
在RemoteMembershipProvider初始化的时候通过调用MembershipService获取所有服务端MembershipProvider的配置信息。
为此,我们为MembershipProvider的所有属性定义了一个数据契约:
MembershipConfigData。
在PetShop中,MembershipConfigData和服务契约一起定义在Infrastructures.Service.Interface项目中。
1:
usingSystem.Runtime.Serialization;
2:
usingSystem.Web.Security;
3:
namespaceArtech.PetShop.Infrastructures.Service.Interface
4:
{
5:
[DataContract(Namespace="
6:
publicclassMembershipConfigData
7:
{
8:
[DataMember]
9:
publicstringApplicationName
10:
{get;set;}
11:
12:
[DataMember]
13:
publicboolEnablePasswordReset
14:
{get;set;}
15:
16:
[DataMember]
17:
publicboolEnablePasswordRetrieval
18:
{get;set;}
19:
20:
[DataMember]
21:
publicintMaxInvalidPasswordAttempts
22:
{get;set;}
23:
24:
[DataMember]
25:
publicintMinRequiredNonAlphanumericCharacters
26:
{get;set;}
27:
28:
[DataMember]
29:
publicintMinRequiredPasswordLength
30:
{get;set;}
31:
32:
[DataMember]
33:
publicintPasswordAttemptWindow
34:
{get;set;}
35:
36:
[DataMember]
37:
publicMembershipPasswordFormatPasswordFormat
38:
{get;set;}
39:
40:
[DataMember]
41:
publicstringPasswordStrengthRegularExpression
42:
{get;set;}
43:
44:
[DataMember]
45:
publicboolRequiresQuestionAndAnswer
46:
{get;set;}
47:
48:
[DataMember]
49:
publicboolRequiresUniqueEmail
50:
{get;set;}
51:
}
52:
}
在服务契约中,定义了一个额外的方法GetMembershipConfigData获取服务端MembershipProvider的所有配置信息,而对于服务操作的定义,则与MembershipProvider同名抽象方法相对应。
1:
usingSystem.ServiceModel;
2:
usingSystem.Web.Security;
3:
namespaceArtech.PetShop.Infrastructures.Service.Interface
4:
{
5:
[ServiceContract(Namespace="
6:
publicinterfaceIMembershipService
7:
{
8:
[OperationContract]
9:
boolChangePassword(stringusername,stringoldPassword,stringnewPassword);
10:
[OperationContract]
11:
boolChangePasswordQuestionAndAnswer(stringusername,stringpassword,stringnewPasswordQuestion,stringnewPasswordAnswer);
12:
[OperationContract]
13:
MembershipUserCreateUser(stringusername,stringpassword,stringemail,stringpasswordQuestion,stringpasswordAnswer,boolisApproved,objectproviderUserKey,outMembershipCreateStatusstatus);
14:
[OperationContract]
15:
boolDeleteUser(stringusername,booldeleteAllRelatedData);
16:
[OperationContract]
17:
MembershipUserCollectionFindUsersByEmail(stringemailToMatch,intpageIndex,intpageSize,outinttotalRecords);
18:
[OperationContract]
19:
MembershipUserCollectionFindUsersByName(stringusernameToMatch,intpageIndex,intpageSize,outinttotalRecords);
20:
[OperationContract]
21:
MembershipUserCollectionGetAllUsers(intpageIndex,intpageSize,outinttotalRecords);
22:
[OperationContract]
23:
intGetNumberOfUsersOnline();
24:
[OperationContract]
25:
stringGetPassword(stringusername,stringanswer);
26:
[OperationContract(Name="GetUserByName")]
27:
MembershipUserGetUser(stringusername,booluserIsOnline);
28:
[OperationContract(Name="GetUserByID")]
29:
MembershipUserGetUser(objectproviderUserKey,booluserIsOnline);
30:
[OperationContract]
31:
stringGetUserNameByEmail(stringemail);
32:
[OperationContract]
33:
stringResetPassword(stringusername,stringanswer);
34:
[OperationContract]
35:
boolUnlockUser(stringuserName);
36:
[OperationContract]
37:
voidUpdateUser(MembershipUseruser);
38:
[OperationContract]
39:
boolValidateUser(stringusername,stringpassword);
40:
[OperationContract]
41:
MembershipConfigDataGetMembershipConfigData();
42:
}
43:
}
服务的实现,则异常简单,我们须要做的仅仅是通过Membership.Provider获得当前的MembershipProvider,调用同名的属性或方法即可。
MembershipService定义在Infrastructures.Service中,定义如下:
1:
usingSystem.Web.Security;
2:
usingArtech.PetShop.Infrastructures.Service.Interface;
3:
namespaceArtech.PetShop.Infrastructures.Service
4:
{
5:
publicclassMembershipService:
IMembershipService
6:
{
7:
#regionIMembershipServiceMembers
8:
9:
publicboolChangePassword(stringusername,stringoldPassword,stringnewPassword)
10:
{
11:
returnMembership.Provider.ChangePassword(username,oldPassword,newPassword);
12:
}
13:
14:
publicboolChangePasswordQuestionAndAnswer(stringusername,stringpassword,stringnewPasswordQuestion,stringnewPasswordAnswer)
15:
{
16:
returnMembership.Provider.ChangePasswordQuestionAndAnswer(username,password,newPasswordQuestion,newPasswordAnswer);
17:
}
18:
//其他成员
19:
publicMembershipConfigDataGetMembershipConfigData()
20:
{
21:
returnnewMembershipConfigData
22:
{
23:
ApplicationName=Membership.Provider.ApplicationName,
24:
EnablePasswordReset=Membership.Provider.EnablePasswordReset,
25:
EnablePasswordRetrieval=Membership.Provider.EnablePasswordRetrieval,
26:
MaxInvalidPasswordAttempts=Membership.Provider.MaxInvalidPasswordAttempts,
27:
MinRequiredNonAlphanumericCharacters=Membership.Provider.MinRequiredNonAlphanumericCharacters,
28:
MinRequiredPasswordLength=Membership.Provider.MinRequiredPasswordLength,
29:
PasswordAttemptWindow=Membership.Provider.PasswordAttemptWindow,
30:
PasswordFormat=Membership.Provider.PasswordFormat,
31:
PasswordStrengthRegularExpression=Membership.Provider.PasswordStrengthRegularExpression,
32:
RequiresQuestionAndAnswer=Membership.Provider.RequiresQuestionAndAnswer,
33:
RequiresUniqueEmail=Membership.Provider.RequiresUniqueEmail
34:
};
35:
}
36:
37:
#endregion
38:
}
39:
}
2、RemoteMembershipProvider的实现
由于RemoteMembershipProvider完全通过调用WCF服务的方式提供对所有成员资格功能的实现,所以进行RemoteMembershipProvider配置时,配置相应的终结点就可以了。
1:
xmlversion="1.0"?
>
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
//localhost/PetShop/Infrastructures/MembershipService.svc"behaviorConfiguration="petShopBehavior"binding="ws2007HttpBinding"contract="Artech.PetShop.Infrastructures.Service.Interface.IMembershipService"name="membershipservice"/> 13: 14: 15: 在RemoteMembershipProvider中,通过Initialize方法获取配置的终结点名称并创建服务代理。 通过该代理调用GetMembershipConfigData操作获取服务端MembershipProvider的配置信息,并对RemoteMembershipProvider进行初始化,RemoteMembershipProvider定义如下: 1: usingSystem.Collections.Specialized; 2: usingSystem.Configuration; 3: usingSystem.Linq; 4: usingSystem.Web.Security; 5: usingArtech.PetShop.Common; 6: usingArtech.PetShop.Infrastructures.Service.Interface; 7: 8: namespaceArtech.PetShop.Infrastructures 9: { 10: publicclassRemoteMembershipProvider: MembershipProvider 11: { 12: privatebool_enablePasswordReset; 13: privatebool_enablePasswordRetrieval; 14: //其他字段成员 15: 16: publicIMembershipServiceMembershipProxy 17: {get;privateset;} 18: 19: publicoverrideintMaxInvalidPasswordAttempts 20: { 21: get{returnthis._maxInvalidPasswordAttempts;} 22: } 23: 24: //其他属性成员 25: publicoverridevoidInitialize(stringname,NameValueCollectionconfig) 26: { 27: if(! config.AllKeys.Contains 28: { 29: thrownewConfigurationErrorsException("Missingthemandatory\"endpoint\"configuraitonproperty."); 30: } 31: 32: this.MembershipProxy=ServiceProxyFactory.Create 33: base.Initialize(name,config); 34: MembershipConfigDataconfigData=this.MembershipProxy.GetMembershipConfigData(); 35: this.ApplicationName=configData.ApplicationName; 36: this._enablePasswordReset=configData.EnablePasswordReset; 37: this._enablePasswordRetrieval=configData.EnablePasswordRetrieval; 38: //...... 39: } 40: } 41: } 对于其他抽象方法的实现,仅仅须要通过上面创建的服务代理,调用相应的服务操作即可。 注: 为了避免在服务操作调用后频繁地进行服务代理的关闭(Close)和终止(Abort)操作,我们采用基于AOP的方式实现服务的调用,将这些操作封装到一个自定义的RealProxy中,并通过ServiceProxyFactory
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 实现 分布式 Membership 上下文 传递