ASP.NET 歪博2.0
得意时淡然,失意时泰然。

在本系列的第一和 第二部分,我们介绍了ASP.NET Provider的概念和内部体系结构,我们知道provider模型是可以扩展的,我们可以自己定义自己的模型结构来完成更适合自己需求的Provider。本文将自定义自己的两个Providers--一个是成员membership Provider,另外一个是角色Role Provider

 

为什么开发自定义MembershipRoleProvider

怎么说呢,原因可能很多,下面列出了部分原因:

你使用了其它数据库(也就是不是SQL Server或者Access数据库)来存放你的数据

你使用了一些非标准的数据库而这些数据库并没有内置的membershiprole Providers模型

你想要执行数据在包含和检索过程具有加密的功能

你想要自己写数据库的处理而非以来于membershiprole  Provider模型

 

需求

现在让我们决定自定的membershiprole Provider需要什么要求:

我们想要使用我们自己的数据库来存放membershiprole信息,这就意味者我们不需要使用中间数据存储应用程序的名称

我们使用自定义的Users表来存放成员关系的详细信息

我们使用自定义的Roles表存放系统里可以使用的角色

我们使用UserRoles表来映射User-Role的关联

 

为了简化本示例,我们不再提供如下功能

密码的“加密-解密”功能

用户注册时主要输入用户名,密码和邮件即可,不用输入安全提问和答案

我们不需要诸如密码恢复,账号锁定等功能

 

数据访问

 这里我们使用BinaryIntellect DatabaseHelper 来完成本模块的数据库访问

 

建立Web站点

  首先,建立一个Web站点,然后在App_Code目录学建立两个类:MyMembershipProvider MyRoleProvider。为了简化应用程序,我们建立webSite本身需要的必要类。在实际的应用中,你可以建立单独的类来包含这些类。

 

配置Web应用程序使用自定义Providers

 打开web.config并增加如下的标记:

 

 1<membership defaultProvider="mymembershipprovider">
 2
 3<providers>
 4
 5<add name="mymembershipprovider" 
 6
 7type="MyMembershipProvider" 
 8
 9connectionStringName="connstr"/>
10
11</providers>
12
13</membership>
14


 1<roleManager enabled="true" defaultProvider="myrolesprovider"> 
 2
 3<providers> 
 4
 5<add name="myrolesprovider" 
 6
 7type="MyRolesProvider" 
 8
 9connectionStringName="connstr"/> 
10
11</providers>
12
13</roleManager>
14
15


在这两段代码里,我们告诉ASP.NET系统使用MyMembershipProvider类来作为成员关系的提供者,使用MyRolesProvider类来作为角色的提供者,建立自定义成员关系的Provider

回忆一下第二部分介绍的程序关系Provider模型,我们需要从System.Web.Security.MembershipProvider 类派生出自定义的成员类

MembershipProvider类又是从ProviderBase类继承而来。MembershipProvider类包含几个抽象的方法,你可以在你自定义的类中使用这些方法

如果你使用的是VS.NET开发环境,那么你可以减轻开发的工作。在MembershipProvider类的定义处右击属性,转到MembershipProvider类的定义可以看到其属性/方法

 

下面列出了改类属性/方法以及意义的列表

(天天注: 这里的意义翻译并没有取之原文,因为中文版本的MSDN已经提供了,你可以查看Member Provider类的成员列表)

属性/方法

意义

Initialize()*

初始化提供程序。在这里获取web.config里数据库链接字符串的值,我们需要在自己的类里进行数据库处理

Name*

这里程序自定义Provider的名称。

CreateUser()*

建立一个用户

UpdateUser()*

保护注册用户资料的更改

DeleteUser()*

删除一个用户

GetUser()*

获取一个MembershipUser对象实例

GetAllUsers()*

获取MembershipUserCollection里用户的集合

ChangePassword()*

更改密码

GetPassword()*

从数据源获取指定用户名所对应的密码。

ValidateUser()*

验证数据源中是否存在指定的用户名和密码。

EnablePasswordReset*

指示成员资格提供程序是否配置为允许用户重置其密码。

EnablePasswordRetrieval*

指示成员资格提供程序是否配置为允许用户检索其密码。

RequiresQuestionAndAnswer*

获取一个值,该值指示成员资格提供程序是否配置为要求用户在进行密码重置和检索时回答密码提示问题。

RequiresUniqueEmail*

获取一个值,指示成员资格提供程序是否配置为要求每个用户名具有唯一的电子邮件地址。

ApplicationName

使用自定义成员资格提供程序的应用程序的名称。

MaxInvalidPasswordAttempts

获取锁定成员资格用户前允许的无效密码或无效密码提示问题答案尝试次数。

MinRequiredNonAlphanumericCharacters

获取有效密码中必须包含的最少特殊字符数。

MinRequiredPasswordLength

获取密码所要求的最小长度。

ChangePasswordQuestionAndAnswer()

处理更新成员资格用户的密码提示问题和答案的请求。

FindUsersByEmail()

获取一个成员资格用户的集合,这些用户的电子邮件地址包含要匹配的指定电子邮件地址。

FindUsersByName()

获取一个成员资格用户的集合,这些用户的用户名包含要匹配的指定用户名。

GetNumberOfUsersOnline()

获取当前访问该应用程序的用户数。

GetUser()

从数据源获取成员资格用户的信息。

GetUserNameByEmail()

利用邮件获取用户名

PasswordAttemptWindow

指示密码输入间隔的时间

PasswordFormat

密码格式,例如明文,Hash表等

PasswordStrengthRegularExpression

密码使用的正则表达式

ResetPassword()

重置用户密码

UnlockUser()

接锁用户

 

在我们的代码里,我们将重载上面列出的前面具有“*”标记的属性或者方法,其它的属性方法只简单的抛出一个“没有执行”的异常

完整的源代码请见下载文件里的MyMembershipProvider.cs,部分代码如下

(天天注:这里引用了更多的源代码)

 

  1using BinaryIntellect.DataAccess;
  2
  3 
  4
  5public class MyMembershipProvider:MembershipProvider
  6
  7{
  8
  9    private DatabaseHelper db = null;
 10
 11public override void Initialize(string name, System.Collections.Specialized.NameValueCollection config)
 12
 13    {
 14
 15string connstr = ConfigurationManager.ConnectionStrings[config["connectionStringName"]].ConnectionString;
 16
 17        db = new DatabaseHelper(connstr);
 18
 19    }

 20
 21 
 22
 23    public override string Name
 24
 25    {    get {  return "MyMembershipProvider";     }
 26
 27    }

 28
 29 
 30
 31    public override MembershipUser CreateUser(string username, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved, object providerUserKey, out MembershipCreateStatus status)
 32
 33    {
 34
 35        MembershipUser user = new MembershipUser(Name, username, providerUserKey, email, passwordQuestion, null, isApproved, false, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now, DateTime.Now);
 36
 37        string sql = "INSERT INTO USERS(USERNAME,PASSWORD,EMAIL,ISACTIVE) VALUES(@UID,@PWD,@EMAIL,@ISACTIVE)";
 38
 39        db.AddParameter("@UID", username);
 40
 41        db.AddParameter("@PWD", password);
 42
 43        db.AddParameter("@EMAIL", email);
 44
 45        db.AddParameter("@ISACTIVE", (isApproved == true ? "Y" : "N"));
 46
 47        int i = db.ExecuteNonQuery(sql);
 48
 49 
 50
 51        if (i > 0)
 52
 53        {
 54
 55            status = MembershipCreateStatus.Success;
 56
 57            return user;
 58
 59        }

 60
 61        else
 62
 63        {
 64
 65            status = MembershipCreateStatus.ProviderError;
 66
 67            return null;
 68
 69        }

 70
 71 
 72
 73    }

 74
 75 
 76
 77    public override void UpdateUser(MembershipUser user)
 78
 79    {
 80
 81        string sql = "UPDATE USERS SET EMAIL=@EMAIL,ISACTIVE=@ISACTIVE WHERE USERNAME=@UID";
 82
 83        db.AddParameter("@EMAIL", user.Email);
 84
 85        db.AddParameter("@ISACTIVE", (user.IsApproved ? "Y" : "N"));
 86
 87        db.AddParameter("@UID", user.UserName);
 88
 89        int i = db.ExecuteNonQuery(sql);
 90
 91    }

 92
 93 
 94
 95    public override bool DeleteUser(string username, bool deleteAllRelatedData)
 96
 97    {
 98
 99        string sql = "DELETE FROM USERS WHERE USERNAME=@UID";
100
101        db.AddParameter("@UID", username);
102
103        int i = db.ExecuteNonQuery(sql);
104
105        if (i > 0)
106
107            return true;
108
109        else
110
111            return false;
112
113 
114
115    }

116
117 
118
119    public override MembershipUser GetUser(string username, bool userIsOnline)
120
121    {
122
123        MembershipUser user = null;
124
125        string sql = "SELECT * FROM USERS WHERE USERNAME=@UID AND ISACTIVE='Y'";
126
127        db.AddParameter("@UID", username);
128
129        SqlDataReader reader = (SqlDataReader)db.ExecuteReader(sql);
130
131        while (reader.Read())
132
133        {
134
135            user = new MembershipUser(Name, reader.GetString(reader.GetOrdinal("username")), null, reader.GetString(reader.GetOrdinal("email")), nullnull, (reader.GetString(reader.GetOrdinal("isactive")) == "Y" ? true : false), false, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue);
136
137        }

138
139        reader.Close();
140
141        return user;
142
143    }

144
145 
146
147    public override MembershipUserCollection GetAllUsers(int pageIndex, int pageSize, out int totalRecords)
148
149    {
150
151        MembershipUserCollection users = new MembershipUserCollection();
152
153        object obj=db.ExecuteScalar("SELECT COUNT(*) FROM USERS");
154
155        int reccount=0;
156
157        if (obj != null)
158
159            reccount = (int)obj;
160
161        SqlDataReader reader = (SqlDataReader)db.ExecuteReader("SELECT * FROM USERS ORDER BY USERNAME");
162
163        while (reader.Read())
164
165        {
166
167            MembershipUser user = new MembershipUser(Name, reader.GetString(reader.GetOrdinal("username")), null, reader.GetString(reader.GetOrdinal("email")), nullnull, (reader.GetString(reader.GetOrdinal("isactive")) == "Y" ? true : false), false, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue, DateTime.MinValue);
168
169            users.Add(user);
170
171        }

172
173        reader.Close();
174
175        totalRecords = reccount;
176
177        return users;
178
179    }

180
181 
182
183    #endregion
184
185 
186
187    Password Management
238
239 
240
241    Authentication
276
277 
278
279    Provider Configuration
346
347 
348
349}

350
351

 

建立自定义的角色Provider

 该类完成列表请参考MSDN:RoleProvider

属性/方法

意义

Initialize()*

初始化提供程序。

Name*

显示自定义Provider的名称

CreateRole*

在数据源中为已配置的 applicationName 添加一个新角色。

DeleteRole*

从数据源中移除已配置的 applicationName 的角色。

GetAllRoles*

获取已配置的 applicationName 的所有角色的列表。

RoleExists*

获取一个值,该值指示指定角色名是否已存在于已配置的 applicationName 的角色数据源中。

AddUsersToRoles*

将指定用户名添加到已配置的 applicationName 的指定角色名。

RemoveUsersFromRoles*

移除已配置的 applicationName 的指定角色中的指定用户名。

GetRolesForUser*

获取指定用户对于已配置的 applicationName 所属于的角色的列表。

GetUsersInRole*

获取属于已配置的 applicationName 的指定角色的用户的列表。

IsUserInRole*

获取一个值,指示指定用户是否属于已配置的 applicationName 的指定角色。

ApplicationName

获取或设置要存储和检索其角色信息的应用程序的名称。

FindUsersInRole

获取属于某个角色且与指定的用户名相匹配的用户名的数组。

在我们的代码里,我们将重载上面列出的前面具有“*”标记的属性或者方法,其它的属性方法只简单的抛出一个“没有执行”的异常

下面列出了部分代码

  1using System;
  2
  3using System.Data;
  4
  5using System.Data.SqlClient;
  6
  7using System.Configuration;
  8
  9using System.Web;
 10
 11using System.Web.Security;
 12
 13using System.Web.UI;
 14
 15using System.Web.UI.WebControls;
 16
 17using System.Web.UI.WebControls.WebParts;
 18
 19using System.Web.UI.HtmlControls;
 20
 21using BinaryIntellect.DataAccess;
 22
 23using System.Collections;
 24
 25 
 26
 27public class MyRolesProvider:RoleProvider
 28
 29{
 30
 31    private DatabaseHelper db = null;
 32
 33 
 34
 35    General
 66
 67 
 68
 69    Role Management
166
167 
168
169    Users and Roles


 

测试自定义Provider

   在你下载的页面里包含了四个Web窗体--default.aspxLogin.aspxRoleManager.aspxUserRoles.aspx。前面两个用于测试成员关系的Provider模型,后面两个用户测试角色的Provider模型。

我们使用了ASP.NET2.0提供的MembershipRoles的基本功能,这些类会使用我们自定义的Provider来完成相应的工作

 

总结

  在本文我们我们可以看到自定义MembershipRole是多么的简单。你可以扩展该功能来适用你的应用程序,你还可以扩展诸如加密解密等功能

posted on 2007-05-21 00:54  Jerry.liu  阅读(486)  评论(0编辑  收藏  举报