专题八的上篇大致讨论了MemberRole中的Membership实现,对于运用Membership进行web开发足够,但是对于想更深入了解Membership实现机理的朋友那是远远不够的,这个专题我们更深入一下了解Membership。
其实MemberRole是一个非常好的资源包,借住Reflector这个优秀的工具,你可以对其进行代码分析。它无论是在组建的构架、代码的设计、数据库表的建立、存储过程的使用等都是非常优秀的,你是程序员也好构架师也罢,其中可以学习的真的很多很多,我在整个分析的过程中也深深受益。
由于MemberRole中的Membership只实现了对SQL Server的操Provider类,即SqlMembershipProvider类。因此我们从SqlMembershipProvider开始分析。Provider模型在上篇已经做过介绍,SqlMembershipProvider类继承了MembershipProvider,并实现其所有的抽象方法。在分析之前先看两个类:MembershipUser与MembershipUserCollection。
MembershipUser,先看看代码:(代码中省略的具体实现,只有方法与属性名称)
public class MembershipUser
{
// Methods
protected MembershipUser();
public MembershipUser(MembershipProvider provider, string name, object providerUserKey, string email, string passwordQuestion, string comment, bool isApproved, bool isLockedOut, DateTime creationDate, DateTime lastLoginDate, DateTime lastActivityDate, DateTime lastPasswordChangedDate, DateTime lastLockoutDate);
public virtual bool ChangePassword(string oldPassword, string newPassword);
public virtual bool ChangePasswordQuestionAndAnswer(string password, string newPasswordQuestion, string newPasswordAnswer);
public virtual string GetPassword();
public virtual string GetPassword(string passwordAnswer);
public virtual string ResetPassword();
public virtual string ResetPassword(string passwordAnswer);
public override string ToString();
public virtual bool UnlockUser();
internal virtual void Update();
private void UpdateSelf();
// Properties
public virtual string Comment { get; set; }
public virtual DateTime CreationDate { get; }
public virtual string Email { get; set; }
public virtual bool IsApproved { get; set; }
public virtual bool IsLockedOut { get; }
public bool IsOnline { get; }
public virtual DateTime LastActivityDate { get; set; }
public virtual DateTime LastLockoutDate { get; }
public virtual DateTime LastLoginDate { get; set; }
public virtual DateTime LastPasswordChangedDate { get; }
public virtual string PasswordQuestion { get; }
public virtual MembershipProvider Provider { get; }
public virtual object ProviderUserKey { get; }
public virtual string UserName { get; }
// Fields
private string _Comment;
private DateTime _CreationDate;
private string _Email;
private bool _IsApproved;
private bool _IsLockedOut;
private DateTime _LastActivityDate;
private DateTime _LastLockoutDate;
private DateTime _LastLoginDate;
private DateTime _LastPasswordChangedDate;
private string _PasswordQuestion;
private MembershipProvider _Provider;
private object _ProviderUserKey;
private string _UserName;
}
这是一个实体类,表示一个由Membership创建的User,该类中有这个User的一些基本状态,如该User的UserName、Email等,还有一些方法,如ChangePassword()、ResetPassword()等(如果你是初学者,还在为建立一个对象需要什么属性,包含什么方法发愁,那这就是你应该好好学的,这也是OOP最基本的要求)。
MembershipUserCollection,这是一个MembershipUser类的容器,用来存放MembershipUser列表,记得上次广州.net俱乐部聚会时,我的演讲中有朋友在提出CS是否使用自定义类来存储用户列表,其实在这里可以看到CS中使用的就是自定义的类而不是DataSet(我想在asp.net 2.0正式发布后这也不会改变),这样做主要是因为考虑到性能与灵活性。
好了,回到SqlMembershipProvider类上来,我们具体分析一个有代表性质的方法:
public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
{
string text3;
MembershipUser user1;
if (!SecUtility.ValidateParameter(ref password, true, true, false, 0x80))
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}
string text1 = base.GenerateSalt();
string text2 = base.EncodePassword(password, (int) this._PasswordFormat, text1);
if (text2.Length > 0x80)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}
if (passwordAnswer != null)
{
passwordAnswer = passwordAnswer.Trim();
}
if ((passwordAnswer != null) && (passwordAnswer.Length > 0))
{
if (passwordAnswer.Length > 0x80)
{
status = MembershipCreateStatus.InvalidAnswer;
return null;
}
text3 = base.EncodePassword(passwordAnswer.ToLower(CultureInfo.InvariantCulture), (int) this._PasswordFormat, text1);
}
else
{
text3 = passwordAnswer;
}
if (!SecUtility.ValidateParameter(ref text3, this.RequiresQuestionAndAnswer, this.RequiresQuestionAndAnswer, false, 0x80))
{
status = MembershipCreateStatus.InvalidAnswer;
return null;
}
if (!SecUtility.ValidateParameter(ref username, true, true, true, 0x100))
{
status = MembershipCreateStatus.InvalidUserName;
return null;
}
if (!SecUtility.ValidateParameter(ref email, this.RequiresUniqueEmail, this.RequiresUniqueEmail, false, 0x100))
{
status = MembershipCreateStatus.InvalidEmail;
return null;
}
if (!SecUtility.ValidateParameter(ref passwordQuestion, this.RequiresQuestionAndAnswer, this.RequiresQuestionAndAnswer, false, 0x100))
{
status = MembershipCreateStatus.InvalidQuestion;
return null;
}
if ((providerUserKey != null) && !(providerUserKey is Guid))
{
status = MembershipCreateStatus.InvalidProviderUserKey;
return null;
}
if (password.Length < this.MinRequiredPasswordLength)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}
int num1 = 0;
for (int num2 = 0; num2 < password.Length; num2++)
{
if (!char.IsLetterOrDigit(password, num2))
{
num1++;
}
}
if (num1 < this.MinRequiredNonAlphanumericCharacters)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}
if ((this.PasswordStrengthRegularExpression.Length > 0) && !Regex.IsMatch(password, this.PasswordStrengthRegularExpression))
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}
ValidatePasswordEventArgs args1 = new ValidatePasswordEventArgs(username, password, true);
this.OnValidatingPassword(args1);
if (args1.Cancel)
{
status = MembershipCreateStatus.InvalidPassword;
return null;
}
try
{
SqlConnectionHolder holder1 = null;
try
{
holder1 = SqlConnectionHelper.GetConnection(this._sqlConnectionString, true);
this.CheckSchemaVersion(holder1.Connection);
SqlCommand command1 = new SqlCommand("dbo.aspnet_Membership_CreateUser", holder1.Connection);
command1.CommandTimeout = this.CommandTimeout;
command1.CommandType = CommandType.StoredProcedure;
command1.Parameters.Add(this.CreateInputParam("@ApplicationName", SqlDbType.NVarChar, this.ApplicationName));
command1.Parameters.Add(this.CreateInputParam("@UserName", SqlDbType.NVarChar, username));
command1.Parameters.Add(this.CreateInputParam("@Password", SqlDbType.NVarChar, text2));
command1.Parameters.Add(this.CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, text1));
command1.Parameters.Add(this.CreateInputParam("@Email", SqlDbType.NVarChar, email));
command1.Parameters.Add(this.CreateInputParam("@PasswordQuestion", SqlDbType.NVarChar, passwordQuestion));
command1.Parameters.Add(this.CreateInputParam("@PasswordAnswer", SqlDbType.NVarChar, text3));
command1.Parameters.Add(this.CreateInputParam("@IsApproved", SqlDbType.Bit, isApproved));
command1.Parameters.Add(this.CreateInputParam("@UniqueEmail", SqlDbType.Int, this.RequiresUniqueEmail ? 1 : 0));
command1.Parameters.Add(this.CreateInputParam("@PasswordFormat", SqlDbType.Int, (int) this.PasswordFormat));
command1.Parameters.Add(this.GetTimeZoneAdjustmentParam());
SqlParameter parameter1 = this.CreateInputParam("@UserId", SqlDbType.UniqueIdentifier, providerUserKey);
parameter1.Direction = ParameterDirection.InputOutput;
command1.Parameters.Add(parameter1);
parameter1 = new SqlParameter("@ReturnValue", SqlDbType.Int);
parameter1.Direction = ParameterDirection.ReturnValue;
command1.Parameters.Add(parameter1);
object obj1 = command1.ExecuteScalar();
DateTime time1 = this.RoundToSeconds(DateTime.Now);
if ((obj1 != null) && (obj1 is DateTime))
{
time1 = (DateTime) obj1;
}
int num3 = (parameter1.Value != null) ? ((int) parameter1.Value) : -1;
if ((num3 < 0) || (num3 > 11))
{
num3 = 11;
}
status = (MembershipCreateStatus) num3;
if (num3 != 0)
{
return null;
}
providerUserKey = new Guid(command1.Parameters["@UserId"].Value.ToString());
return new MembershipUser(this, username, providerUserKey, email, passwordQuestion, null, isApproved, false, time1, time1, time1, time1, new DateTime(0x6da, 1, 1));
}
finally
{
if (holder1 != null)
{
holder1.Close();
holder1 = null;
}
}
}
catch
{
throw;
}
return user1;
}
[1] [2] 下一页 |