在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本篇将完成 XmlMembershipProvider 类,它是自定义存储和成员资格 API 需求之间适配器的角色。
每一个自定义的成员资格提供程序必须从这个类继承。(ASP.NET 4.0 中移到了 System.Web.ApplicationServices.dll 中) 需要实现很多属性和方法来满足成员资格 API 的需要。这些属性和方法用来查询、创建、更新、删除用户,以及获取提供程序的特定信息,比如密码要求等。这些属性会由安全控件来查询,比如 RequiresQuestionAndAnswer 属性由 CreateUserWizard 向导来查询。 先实现这些属性,这是最简单的部分。对于每一个属性,都应提供一个包含相应属性状态的私有变量。这些属性的含义与底层提供程序实现中的含义相同。属性中的大部分只有访问方法而没有设置方法。那么,ASP.NET 架构如何用 web.config 中配置的值来初始化这些属性的呢? 在所有提供程序的原始基类 System.Configuration.Provider.ProviderBase 中可以找到答案。重载它的 Initialize() 方法初始化属性的私有成员:
现在一步步的实现 Xml的功能: string name, System.Collections.Specialized.NameValueCollection config)
{ if (config == null) { throw new ArgumentNullException("config"); } if (string.IsNullOrEmpty(name)) { name = "XmlMembershipProvider";
} if (string.IsNullOrEmpty(config["description"])) { config.Remove("description");
config.Add("description", "Xml Membership Provider"); } base.Initialize(name, config);
...... } 首先,检查每一个配置是否都已被传入。如果没有为提供程序做任何配置,它不会工作。调用基类的初始化方法来适当的初始化基本的属性。接着,就开始初始化属性: // Initialize default values
_ApplicationName = "DefaultApp";
_EnablePasswordReset = false;
_PasswordStrengthRegEx = @"[\w| !?%&/()=\-?\*]*";
_MaxInvalidPasswordAttempts = 3; _MinRequiredNonAlphanumericChars = 1; _MinRequiredPasswordLength = 5; _RequiresQuestionAndAnswer = false;
_PasswordFormat = MembershipPasswordFormat.Hashed; // Now go through the properties and initialize custom values
foreach (string key in config.Keys) { switch (key.ToLower())
{ case "name": _Name = config[key]; break;
case "applicationname": _ApplicationName = config[key]; break;
case "filename": _FileName = config[key]; break;
case "enablepasswordreset": _EnablePasswordReset = bool.Parse(config[key]);
break;
case "passwordstrengthregex": _PasswordStrengthRegEx = config[key]; break;
case "maxinvalidpasswordattempts": _MaxInvalidPasswordAttempts = int.Parse(config[key]);
break;
case "minrequirednonalphanumericchars": _MinRequiredNonAlphanumericChars = int.Parse(config[key]);
break;
case "minrequiredpasswordlength": _MinRequiredPasswordLength = int.Parse(config[key]);
break;
case "passwordformat": _PasswordFormat = (MembershipPasswordFormat)Enum.Parse( typeof(MembershipPasswordFormat), config[key]);
break;
case "requiresquestionandanswer": _RequiresQuestionAndAnswer = bool.Parse(config[key]);
break;
} } 这些代码初始化一些默认值,以防这些属性没有包含在 web.config 配置文件中。你甚至可以包含自定义设置,比如文件名设置 _FileName 属性(它不是成员资格提供程序的默认属性),它指向一个用来存储用户信息的 XML 文件。将这个文件名传递给 UserStore 类: private UserStore CurrentStore
{ get { if (_CurrentStore == null) { _CurrentStore = UserStore.GetStore(_FileName); } return _CurrentStore;
} } 在这个类的其余函数中,会一直用到这个属性访问数据存储。
提供程序中需要实现大量的方法,它们用来创建、更新和删除用户,以及访问并获取用户的详细信息。这些方法通过前面创建的存储类来访问这些信息。
1. 创建用户并将它们添加到存储CreateUser() 方法需要确保用户名和 Email 地址是唯一的,而且密码是有效的并且符合密码强度的要求。 public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status) { try
{ // Validate the username and email
if (!ValidateUsername(username, email, Guid.Empty))
{ status = MembershipCreateStatus.InvalidUserName; return null; } // Raise the event before validating the password
base.OnValidatingPassword(new ValidatePasswordEventArgs(username, password, true)); // Validate the password
if (!ValidatePassword(password))
{ status = MembershipCreateStatus.InvalidPassword; return null; } // Everything is valid, create the user
SimpleUser user = new SimpleUser();
user.UserKey = Guid.NewGuid(); user.UserName = username; user.PasswordSalt = string.Empty;
user.Password = this.TransformPassword(password, ref user.PasswordSalt); user.Email = email; user.PasswordQuestion = passwordQuestion; user.PasswordAnswer = passwordAnswer; user.CreationDate = DateTime.Now; user.LastActivityDate = DateTime.Now; user.LastPasswordChangeDate = DateTime.Now; // Add the user to the store
CurrentStore.Users.Add(user); CurrentStore.Save(); status = MembershipCreateStatus.Success; return CreateMembershipFromInternalUser(user);
} catch
{ throw;
} } 刚开始,CreateUser() 调用了私有辅助方法 ValidateUsername 和 ValidatePassword,这些方法确定用户名和 Email 在存储中是唯一的,并确定密码符合要求。当这些检查成功后,就可以为底层存储(SimpleUser)创建用户了。 最后,这个方法需要返回 MembershipUser 的实例,并将其传递给调用它的 Membership 类,该实例包含了被创建的用户的详细信息。为此,只需要将 SimpleUser 实例的属性和 MembershipUser 的属性相匹配就可以了: private MembershipUser CreateMembershipFromInternalUser(SimpleUser user)
{ MembershipUser muser = new MembershipUser(base.Name, user.UserName, user.UserKey, user.Email, user.PasswordQuestion, string.Empty, true, false, user.CreationDate, user.LastLoginDate, user.LastActivityDate, user.LastPasswordChangeDate, DateTime.MaxValue); return muser;
}
来看一下验证用户名、E-mail 地址和密码的方法:首先确认了密码的长度、接着用正则表达式确认密码中非字母数字字符的个数是否符合 MinRequiredNonAlphanumericCharacters 属性设置的要求,然后使用 PasswordStrengthRegularExpression 属性设置的正则表达式验证密码规范,通过这 3 项检查就返回 true。 private bool ValidateUsername(string userName, string email, Guid excludeKey) { bool IsValid = true; UserStore store = UserStore.GetStore(_FileName); foreach (SimpleUser user in store.Users) { if (user.UserKey.CompareTo(excludeKey) != 0)
{ if (string.Equals(user.UserName, userName, StringComparison.OrdinalIgnoreCase)) { IsValid = false;
break;
} if (string.Equals(user.Email, email, StringComparison.OrdinalIgnoreCase)) { IsValid = false;
break;
} } } return IsValid;
} private bool ValidatePassword(string password) { bool IsValid = true; Regex HelpExpression; 全部评论
专题导读
热门推荐
热门话题
阅读排行榜
|
请发表评论