• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

ASP.NET 自定义成员资格提供程序 Part.2(实现提供程序类:XmlMembershipProvider) ...

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

       本篇将完成 XmlMembershipProvider 类,它是自定义存储和成员资格 API 需求之间适配器的角色

public class XmlMembershipProvider : System.Web.Security.MembershipProvider { }

       每一个自定义的成员资格提供程序必须从这个类继承。(ASP.NET 4.0 中移到了 System.Web.ApplicationServices.dll 中)

       需要实现很多属性和方法来满足成员资格 API 的需要。这些属性和方法用来查询、创建、更新、删除用户,以及获取提供程序的特定信息,比如密码要求等。这些属性会由安全控件来查询,比如 RequiresQuestionAndAnswer 属性由 CreateUserWizard 向导来查询。

       先实现这些属性,这是最简单的部分。对于每一个属性,都应提供一个包含相应属性状态的私有变量。这些属性的含义与底层提供程序实现中的含义相同。属性中的大部分只有访问方法而没有设置方法。那么,ASP.NET 架构如何用 web.config 中配置的值来初始化这些属性的呢?

       在所有提供程序的原始基类 System.Configuration.Provider.ProviderBase 中可以找到答案。重载它的 Initialize() 方法初始化属性的私有成员:

public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config){}

 

       现在一步步的实现 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;

 
                    
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
防止ASP.NET按钮多次提交的办法及延伸发布时间:2022-07-10
下一篇:
ASP.NET MVC学习系列(二)-WebAPI请求发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap