日期:2010-11-06  浏览次数:20425 次

  摘要: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是无法使用到这些方法的。而且从目前应用范围来看,目前这些方法也只有在SqlM