温故知新 Membership MembershipUser MembershipProvider
Membership API最初在.net 2.0中被引入,所有相关的类都在System.Web.Security命名空间中。
一.MembershipProvider类
这是一个抽象类,可以理解为一个接口规范。其中定义了一些抽象方法,譬如CreateUser,UpdateUser,DeleteUser等,这些方法名很直观的描述了它们的用途。
public abstract class MembershipProvider : ProviderBase
{
// Fields
private MembershipValidatePasswordEventHandler _EventHandler;
// Events
public event MembershipValidatePasswordEventHandler ValidatingPassword;
// Methods
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
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);
[TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
protected virtual byte[] EncryptPassword(byte[] password);
protected virtual byte[] EncryptPassword(byte[] password, MembershipPasswordCompatibilityMode legacyPasswordCompatibilityMode);
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);
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);
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; }
}
通过继承,重写该类的方法来实现具体功能。可以参考下SqlMembershipProvider,它就是继承MembershipProvider,重写抽象方法,实现与MSSQL的互操作,类似的还有ActiveDirectoryMembershipProvider。
二.SqlMembershipProvider类
上面说到,一般我们是通过继承MembershipProvider类,然后重写方法,实现自己的功能。.net中已经内置了两个实现的MembershipProvider的Provider,SqlMemberShipProvider和ActiveDirectoryMemberShipProvider。SqlMemberShipProvider就是一个封装了与MSSQL操作相关的类。在使用SqlMembershipProvider进行数据库相关操作前,当然要先创建一个数据库,这个数据库包含约定好的表结构、约定好的存储过程等等,与SqlMembershipProvider配套使用。
创建数据库的方法,就我知道的有3种:
1.通过Visual Studio命令直接创建数据库
2.通过ASP.NET SQL Server安装向导,直接在命令行中输入aspnet_regsql进入向导
3.在.NET Framework目录会有sql安装的脚本InstallXXX.sql,还会有对应的UninstallXXX.sql:
创建好数据库后,还需要在web.config中配置(提供给Membership类使用的),在Membership类的介绍中再具体做说明。
SqlMemberShipProvider类中的DeleteUser方法的具体实现:
{
bool flag;
SecUtility.CheckParameter(ref username, true, true, true, 0x100, "username");
try
{
SqlConnectionHolder connection = null;
try
{
connection = SqlConnectionHelper.GetConnection(this._sqlConnectionString, true);
this.CheckSchemaVersion(connection.Connection);
SqlCommand command = new SqlCommand("dbo.aspnet_Users_DeleteUser", connection.Connection);
command.CommandTimeout = this.CommandTimeout;
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add(this.CreateInputParam("@ApplicationName", SqlDbType.NVarChar, this.ApplicationName));
command.Parameters.Add(this.CreateInputParam("@UserName", SqlDbType.NVarChar, username));
if (deleteAllRelatedData)
{
command.Parameters.Add(this.CreateInputParam("@TablesToDeleteFrom", SqlDbType.Int, 15));
}
else
{
command.Parameters.Add(this.CreateInputParam("@TablesToDeleteFrom", SqlDbType.Int, 1));
}
SqlParameter parameter = new SqlParameter("@NumTablesDeletedFrom", SqlDbType.Int);
parameter.Direction = ParameterDirection.Output;
command.Parameters.Add(parameter);
command.ExecuteNonQuery();
int num = (parameter.Value != null) ? ((int) parameter.Value) : -1;
flag = num > 0;
}
finally
{
if (connection != null)
{
connection.Close();
connection = null;
}
}
}
catch
{
throw;
}
return flag;
}
它调用了存储过程"dbo.aspnet_Users_DeleteUser",来执行删除用户操作,而操作的数据库就是刚刚创建的。我们可以参照SqlMembershipProvider来实现自己的Provider,写个访问Oracle等数据库的Provider,前提是要继承MembershipProvider,就像事先约定好必须要做哪些事情。最后只需配置web.config即可。
三.Membership类
第二点中有说到配置SqlMembershipProvider,调用DeleteUser来实现删除,那么,是谁来调用DeleteUser方法?就是Membership!Membership中定义了一些方法和MembershipProvider中的一些方法是一样,例如MembershipProvider定义了DeleteUser方法,而Membership也包含同名的方法,并且有具体实现:
{
SecUtility.CheckParameter(ref username, true, true, true, 0, "username");
return Provider.DeleteUser(username, true);
}
这个方法中调用了Provider.DeleteUser(),这个Provider就是从web.config中获取<membership>节点,获取type所指向的System.Web.Security.SqlMembershipProvider,因为我们配置了SqlMembershipProvider,所以通过反射创建的就是SqlMembershipProvider类的实例,
然后再通过SqlMembershipProvider类的实例来调用DeleteUser()完成操作,好处就是可以灵活配置Provider,切换不同的实现。
<providers>
<clear/>
<add name="AspNetSqlMembershipProvider" type="System.Web.Security.SqlMembershipProvider" connectionStringName="connectStrForSqlMembership"
enablePasswordRetrieval="false" enablePasswordReset="true" requiresQuestionAndAnswer="false" requiresUniqueEmail="false"
maxInvalidPasswordAttempts="5" minRequiredPasswordLength="1" minRequiredNonalphanumericCharacters="0" passwordAttemptWindow="10"
applicationName="/" />
</providers>
</membership>
四.MembershipUser类
MembershipUser类定义了一些字段和一些方法,这些字段对应了第二点中创建的数据库中的Membership表的一些字段,应该可以理解为是
一个约定好的Model加上一些常规操作。