设为首页  
联系我们  
加入收藏  
网页制作 冲浪宝典 图形图像 操作系统 软件教学 编程开发 认证考试 安全技术 站长专区 文学驿站 娱乐天地 游戏天地 办公软件
文章搜索
您的位置: 首页 >> 文章首页 >> 编程开发 >> 网络编程 >> ADO.NET应用 >> ASP.NET 2.0 Membership原理及应用
精品推荐
ADO.NET应用点击TOP10
·DataGrid的多行提交
·asp.net中读取和更新xml文件
·ASP.NET数据库编程
·最佳实践 ADO.NET实用经验无保留曝光
·ASP.NET中存取图片到数据库的示例
·ASP.NET 崩溃-SiteMap中疯狂的循环
·小议优化ASP.NET应用性能之ViewState篇
·用ado.net对word,excel进行存取
·ADO.NET入门
·连接SQL SERVER的公共类(VB.NET)
网络编程点击TOP10
·ASP.NET 程序中常用的三十三种代码
·CHK文件恢复工具
·.NET 初 级 读 本
·c#操作word表格
·我的.NET书架 (入门篇)
·『原创』C#中TreeView类操作全攻略:建立树,新增节点,删除节点,修改节点,拖动节点,与Oracle数据库交互操作(一)
·从零开始学ASP.NET(基础篇)
·用C#实现木马程序
·十天学会ASP.net之第一天
·官方水晶报表 .NET 应用程序实例下载 (C#、Visual C++.NET)
精选专题

ASP.NET 2.0 Membership原理及应用

作者: 来源: 时间:2006-8-31 7:35:02

    摘要ASP.net 2.0的Membership组件提供了一组非常简单易用的接口供开发者进行用户管理,用户验证。本文将它对它的实现原理进行简单的分析,介绍如何正确的使用,以及如何对它进扩展。

  一、MembershipProvider抽象类

  在很多情况下,在使用Membership的时候我们并不会直接使用到这个类。在MembershipProvider类定义的都是一些抽象方法和抽象属性,就是这些方法和属性构成了Membership接口的基本规范,而且在.NET 框架内部使用Membership的功能都是通过这个类型调用的。继承类通过实现这些接口来提供不用环境下的用户管理功能,并且对Membership框架本身并没有影响,下面来看看MembershipProvider原形定义:

public abstract class MembershipProvider : ProviderBase

...{

// Events

public event MembershipValidatePassWordEventHandler ValidatingPassword;



// Methods

protected MembershipProvider();

public abstract bool ChangePassword(string username, string oldPassword, string newPassword);

public abstract bool ChangePasswordQuestionAndAnswer(string username, string password, string newPasswordQuestion, string newPasswordAnswer);

public abstract MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);

protected virtual byte[] DecryptPassword(byte[] encodedPassword);

public abstract bool DeleteUser(string username, bool deleteAllRelatedData);

internal string EncodePassword(string pass, int passwordFormat, string salt);

protected virtual byte[] EncryptPassword(byte[] password);

public abstract MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords);

public abstract MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords);

internal string GenerateSalt();

public abstract MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords);

public abstract int GetNumberOfUsersOnline();

public abstract string GetPassword(string username, string answer);

public abstract MembershipUser GetUser(object providerUserKey, bool userIsOnline);

public abstract MembershipUser GetUser(string username, bool userIsOnline);

internal MembershipUser GetUser(string username, bool userIsOnline, bool throwOnError);

public abstract string GetUserNameByEmail(string email);

protected virtual void OnValidatingPassword(ValidatePasswordEventArgs e);

public abstract string ResetPassword(string username, string answer);

internal string UnEncodePassword(string pass, int passwordFormat);

public abstract bool UnlockUser(string userName);

public abstract void UpdateUser(MembershipUser user);

public abstract bool ValidateUser(string username, string password);



// Properties

public abstract string ApplicationName ...{ get; set; }

public abstract bool EnablePasswordReset ...{ get; }

public abstract bool EnablePasswordRetrieval ...{ get; }

public abstract int MaxInvalidPasswordAttempts ...{ get; }

public abstract int MinRequiredNonAlphanumericCharacters ...{ get; }

public abstract int MinRequiredPasswordLength ...{ get; }

public abstract int PasswordAttemptWindow ...{ get; }

public abstract MembershipPasswordFormat PasswordFormat ...{ get; }

public abstract string PasswordStrengthRegularEXPression ...{ get; }

public abstract bool RequiresQuestionAndAnswer ...{ get; }

public abstract bool RequiresUniqueEmail ...{ get; }



// Fields

private MembershipValidatePasswordEventHandler _EventHandler;

private const int SALT_SIZE_IN_BYTES = 0x10;

}

  其中修饰符为internal是几个方法是密码的辅助方法,用于加密,解密和验证密码。但这边的设计似乎有一些问题,将这些方法定义为internal范围好像有点不妥,将这些方法定义在基类中,就是为了能够被复用,但是从效果上来看,不是这样的,因为internal的成员只允许在本程序集内被使用(正常情况下,不包括反射等其它方法),这就是说我们自己扩展的MembershipProvider是无法使用到这些方法的。而且从目前应用范围来看,目前这些方法也只有在SqlMembershipProvider中被使用到,所以我认为应该将这些方法修饰符修改为protected。
    二、Membership 静态类

  上面提到过,一般情况下我们都不会直接去使用到MembershipProvider抽象,因为这涉及到如何去实例化真正的Membership服务类的问题,涉及到配置和实例化对象的问题一般都是比较棘手的问题,对初学者来说,想要掌握也不是那么容易。那在.NET框架中就是通过Membership(Static Class)这个静态类来屏蔽掉这一层的复杂关系。Membership(Static Class)除了使用者屏蔽读配置文件,初始对象等一些基本工作外,还有一个重要的作用就是重载所有的MembershipProvider所以有API,甚至为了让用户更加方便的使用,将这些方法重载为静态方法,并且提供了MembershipProvider基本API基础上更加丰富的重载实现供使用者调用。这就直接支持了不管是在UI层,还是其它的各个工程,只需要引用System.Web.Security命名空间,就可以不用关心任何细节的享受到Membership给我们提供的各种便利。下面来看看Membership(Static Class)的原型定义:(利用Lutz Roder’s .NET Reflector可以查看它的所有实现。)

public static class Membership

...{

// Events

public static event MembershipValidatePasswordEventHandler ValidatingPassword;



// Methods

static Membership();

public static MembershipUser CreateUser(string username, string password);

public static MembershipUser CreateUser(string username, string password, string email);

public static MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, out MembershipCreateStatus status);

public static MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status);

public static bool DeleteUser(string username);

public static bool DeleteUser(string username, bool deleteAllRelatedData);

public static MembershipUserCollection FindUsersByEmail(string emailToMatch);

public static MembershipUserCollection FindUsersByEmail(string emailToMatch, int pageIndex, int pageSize, out int totalRecords);

public static MembershipUserCollection FindUsersByName(string usernameToMatch);

public static MembershipUserCollection FindUsersByName(string usernameToMatch, int pageIndex, int pageSize, out int totalRecords);

public static string GeneratePassword(int length, int numberOfNonAlphanumericCharacters);

public static MembershipUserCollection GetAllUsers();

public static MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords);

private static string GetCurrentUserName();

public static int GetNumberOfUsersOnline();

public static MembershipUser GetUser();

public static MembershipUser GetUser(bool userIsOnline);

public static MembershipUser GetUser(object providerUserKey);

public static MembershipUser GetUser(string username);

public static MembershipUser GetUser(object providerUserKey, bool userIsOnline);

public static MembershipUser GetUser(string username, bool userIsOnline);

public static string GetUserNameByEmail(string emailToMatch);

private static void Initialize();

public static void UpdateUser(MembershipUser user);

public static bool ValidateUser(string username, string password);



// Properties

public static string ApplicationName ...{ get; set; }

public static bool EnablePasswordReset ...{ get; }

public static bool EnablePasswordRetrieval ...{ get; }

public static string HashAlgorithmType ...{ get; }

internal static bool IsHashAlgorithmFromMembershipConfig ...{ get; }

public static int MaxInvalidPasswordAttempts ...{ get; }

public static int MinRequiredNonAlphanumericCharacters ...{ get; }

public static int MinRequiredPasswordLength ...{ get; }

public static int PasswordAttemptWindow ...{ get; }

public static string PasswordStrengthRegularExpression ...{ get; }

public static MembershipProvider Provider ...{ get; }

public static MembershipProviderCollection Providers ...{ get; }

public static bool RequiresQuestionAndAnswer ...{ get; }

public static int UserIsOnlineTimeWindow ...{ get; }

// Fields

private static char[] punctuations;

private static bool s_HashAlgorithmFromConfig;

private static string s_HashAlgorithmType;

private static bool s_Initialized;

private static Exception s_InitializeException;

private static object s_lock;

private static MembershipProvider s_Provider;

private static MembershipProviderCollection s_Providers;

private static int s_UserIsOnlineTimeWindow;

}

  说到这里,就不得不多罗嗦两句。在看Membership(Static Class)实现代码的过程中,可以发现,每一个Membersip API重载都最后都是调用属性Provider的方法,这个属性的类型就是MembershipProvider类型,只有看到这里,你也许才会理解MembershipProvider的重要作用了吧。还有一个Providers属性,这个属性就是获得web.config中配置的所有的Membership提供服务类。它们都是静态属性,但是它们怎么去实例化的呢?就是通过调用Membership. Initialize()这个方法,在每次调用这两个属性的时候,都会调用这个方法去判断是否已初始化了Membership提供服务类了,如果没有则去调用配置服务类,读取配置内容,从而进行初始化。到此你可能也就不难理解了,为什么我们使用那么简单了!

  三、SqlMembershipProvider介绍和使用配置

  OK,通过上面的介绍应该基本可以了解Membership的整体结构了吧?(如何还没有,可能是你没有打开Lutz Roder’s .NET Reflector去分析它的实现代码,或者是对抽象类的作用还没弄明白)。不管怎么样,我们最终的目的就是要学会如何去使用。

  在这之前,我先要介绍一下,在.NET 框架中提供的两个MembershipProvider实现类:ActiveDirectoryMembershipProvider和SqlMembershipProvider(如何知道这两个类的?在MembershipProvider的Derived Types就可以看到所有的继承类了。)前者是提供基本活动目录下的用户管理(我也没有实践过),后者就是我们最经常使用到的基于SqlServer的用户管理实现。

  到了介绍如何使用了,其实园子里已经有了这方面的文章((翻译)怎么在ASP.NET 2.0中使用Membership),我也不多费口舌了。但这边要告诉大家一个最直接的学习和参考使用的办法。在系统盘找到并打开machine.config,找到AspNetSqlMembershipProvider节点:

<membership>
<providers>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" connectionStringName="LocalSqlServer" enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="true" applicationName="/" requiresUniqueEmail="false" passwordFormat="Hashed" maxInvalidPasswordAttempts="5" minRequiredPasswordLength="7" minRequiredNonalphanumericCharacters="1" passwordAttemptWindow="10" passwordStrengthRegularExpression="" />
</providers>
</membership>

  看到没有,其实这个就是一个最基本的Membership配置了,只不过是还少了一个defaultProvider属性的指定,指定了这个属性后,你再使用Login控件,进行用户登录验证就无需使用任何代码了。不信你可以试试。(关于Forms验证,就不在这里多做介绍,可以参考相关资料。关于SqlMembershipProvider的更多属性的介绍可以参看MSDN)。

  四、如何自定义MembershipProvider,现有其它的MembershipProvider资源

  那么,我们如何去自定义一个MembershipProvider呢?其实如果你已经了解了Membership的结构后我相信对你来说已经不是一件很难的事了,但是考虑到要完整的写一个MembershipProvider还是有一定的工作量和难度的。对于我们来说,更多的地方可能是对现有的Provider进行扩展,如SqlMembershipProvider。那其实这是非常简单的,我们只需要继承自SqlMembershipProvider,(悄悄告诉你,在Initialize方法config参数中保存的就是Provider对应配置节的属性名和值)然后扩展和重写所需的方法就可以了。使用的时候,在Provider配置节中,将type的值改为你的类名就OK了。


ASP.NET 2.0 Membership原理及应用 相关文章:
ASP.NET 2.0 Membership原理及应用 相关软件:
特别声明:本站除部分特别声明禁止转载的专稿外的其他文章可以自由转载,但请务必注明出处和原始作者。文章版权归文章原始作者所有。对于被本站转载文章的个人和网站,我们表示深深的谢意。如果本站转载的文章有版权问题请联系编辑人员,我们尽快予以更正。
转载请注明来源:http://www.xgdown.com