引言
在第1部分和第2部分中,我们学习了ASP.NET2.0提供者模型的概念和内部结构。我们知道提供者模型是可扩展的,任何人都可以根据需要实现自己的提供者。在这一部分中,我们将创建两个自定义提供者---一个用于成员资格,另一个用于角色。
为什么要创建自定义的成员资格和角色提供者?
可能有很多原因,下面列举几个:
-
你有自定义的数据存储(不是 SQL SERVER 或者 Access )用来存储用户数据。
-
你要使用非标准的数据库,而 ASP.NET 中没有提供相关的成员资格和角色提供者。
-
你想在保存和获取数据时实现自定义的加密机制。
-
你想编写与数据库无关的成员资格和角色提供者。
还有更多原因并没有列出来---你可能使用自己的表模式,而不是内建的模式。表面看起来比较古怪,但如果你想迁移应用时,这将是非常有用的方法。
约束条件
构建自定义的成员资格和角色提供者需要具备如下条件:
-
我们需要使用应用数据库来存储成员资格和角色信息。这意味着我们并不需要一个数据库中心来存储多个应用的成员资格。
-
我们需要将成员资格详情存储到 Users 表中。
-
我们需要在 Roles 表中存储可用的角色。
-
我们需要存储用户 - 角色映射到 UserRoles 中。
-
为了简单化,我们不包含任何加密 / 解密逻辑。
-
用户通过用户名、密码、电子邮件地址来注册,不要求安全问题。
-
我们不需要重置密码、帐户锁定等功能。
数据库访问
我们使用开源组件BinaryIntellect DatabaseHelper来进行数组库访问。
创建Web站点
首先,创建Web站点,并且添加MyMembershipProvider和MyRoleProvider类到App_Code文件夹。为了简化,我们将创建所有必要的类。在大多数真实世界环境中,你可能需要创建单独的类库项目来包含这些类。
在站点中配置自己的提供者
打开web.config,添加如下内容:
<membership defaultProvider="mymembershipprovider">
<providers>
<add name="mymembershipprovider"
type="MyMembershipProvider"
connectionStringName="connstr"/>
</providers>
</membership>
<roleManager enabled="true" defaultProvider="myrolesprovider">
<providers>
<add name="myrolesprovider"
type="MyRolesProvider"
connectionStringName="connstr"/>
</providers>
</roleManager>
这样,我们通知ASP.NET使用MyMembershipProvider类作为成员资格提供者和MyRoleProvier类作为角色提供者。
创建自定义成员资格提供者
回忆一下第2部分的内容,自定义成员资格提供者需要从System.Web.Security.MembershipProvider类继承。MembershipProvider类依次从ProviderBase类继承。在你的代码中必须实现MembershipProvider类中包含的几个抽象方法。
如果你使用的是VS.NET,工作就会非常简单。在MembershipProvider类上单击右键,选择“实现抽象类”。VS.NET会自动添加所有MembershipProver类的方法和属性.下表列出了这些需要实现的方法和属性。
Property/Method Name | Description |
Initialize()* | Receives the connection string name specified in the web.config file. You can use it to perform database operation in your class. |
Name* | Represents name of our custom provider |
CreateUser()* | Creates a user |
UpdateUser()* | Saves modified information about an existing user |
DeleteUser()* | Deletes a user |
GetUser()* | Gets a user as MembershipUser instance |
GetAllUsers()* | Gets all the users as MembershipUserCollection |
ChangePassword()* | Changes password of a user |
GetPassword()* | Retrieves password of a user. Used when implementing "Forgot Password" feature |
ValidateUser()* | Authenticates the user |
EnablePasswordReset* | Indicates whether the password can be reset by the user |
EnablePasswordRetrieval* | Indicates whether the password can be retrieved by teh user |
RequiresQuestionAndAnswer* | Indicates whether user should supply a security question and answer during registration |
RequiresUniqueEmail* | Indicates whether the email supplied during registration should be unique |
ApplicationName | Name of the web application. This name is used in case you are using a central database for storing membership data of multiple applications |
MaxInvalidPasswordAttempts | Indicates the number of times user can try to login to the system |
MinRequiredNonAlphanumericCharacters | Indicates minimum no. of non alpha numeric characters that the user must supply during registration and password change |
MinRequiredPasswordLength | Indicates the minimum length required for the password when user registers or changes the password |
ChangePasswordQuestionAndAnswer() | Allows to change user's security question and answer |
FindUsersByEmail() | Searches user database on the basis of email |
FindUsersByName() | Searches user database on the basis of user name |
GetNumberOfUsersOnline() | Returns total no. of uses that are signed in |
GetUser() | Returns MembershipUser instance representing a specific user |
GetUserNameByEmail() | Returns the user name on the basis of email |
PasswordAttemptWindow | Indicates the time span for multiple login attempts |
PasswordFormat | Indicates the format of password e.g.clear, hashed etc. |
PasswordStrengthRegularExpression | Indicates a regular expression to be used to check the strength of password |
ResetPassword() | Resets the password |
UnlockUser() | Unlocks the user account |
在我们的示例中,我们将对标记了“*”号的方法和属性编写代码。其它的成员仅仅简单地抛出“尚无实现”异常。
自定义的成员资格提供者的完整实现的源代码在下载中可以获得(MyMembershipProvier.cs)。CreateUser()方法的实现如下:
public override MembershipUser CreateUser
(string username, string password,
string email, string passwordQuestion,
string passwordAnswer, bool isApproved,
object providerUserKey,
out MembershipCreateStatus status)
{
MembershipUser user = new MembershipUser(Name,
username, providerUserKey, email, passwordQuestion,
null, isApproved, false, DateTime.Now, DateTime.Now,
DateTime.Now, DateTime.Now, DateTime.Now);
string sql = "INSERT INTO USERS(USERNAME,PASSWORD,
EMAIL,ISACTIVE) VALUES(@UID,@PWD,@EMAIL,@ISACTIVE)";
db.AddParameter("@UID", username);
db.AddParameter("@PWD", password);
db.AddParameter("@EMAIL", email);
db.AddParameter("@ISACTIVE",
(isApproved == true ? "Y" : "N"));
int i = db.ExecuteNonQuery(sql);
if (i > 0)
{
status = MembershipCreateStatus.Success;
return user;
}
else
{
status = MembershipCreateStatus.ProviderError;
return null;
}
}
创建自定义的角色提供者
创建角色提供者包含创建继承于RoleProvier的类。下表列出了需要实现的方法和属性。
Property/Method Name | Description |
Initialize()* | Receives the connection string name specified in the web.config file. You can use it to perform database operation in your class. |
Name* | Represents name of our custom provider |
CreateRole* | Create a new role |
DeleteRole* | Deletes an existing role |
GetAllRoles* | Returns all roles as string array |
RoleExists* | Checks if role exists in the database |
AddUsersToRoles* | Adds users to specified roles |
RemoveUsersFromRoles* | Removes users from specified roles |
GetRolesForUser* | Returns all the roles for a specific user |
GetUsersInRole* | Returns all the users belonging to a specified role |
IsUserInRole* | Checks if a user exists in a specified role |
ApplicationName | Name of the web application. This name is used in case you are using a central database for storing membership data of multiple applications |
FindUsersInRole | Searches for users belonging to a specified role |
在我们的示例中,我们将对标记了“*”号的方法和属性编写代码。其它的成员仅仅简单地抛出“尚无实现”异常。
自定义的角色提供者的完整实现的源代码在下载中可以获得(MyRolesProvier.cs)。CreateRole()方法的实现如下:
public override void CreateRole(string roleName)
{
db.AddParameter("@ROLE", roleName);
db.ExecuteNonQuery
("INSERT INTO ROLES(ROLENAME) VALUES(@ROLE)");
}
测试自定义提供者
有4个测试窗体可以下载:Default.aspx,、Login.aspx、RoleManager.aspx、UserRoles.aspx。前两个测试成员资格提供者,后两个测试角色提供者。本质上,我们同样使用ASP.NET的成员资格类和角色类,这些类依次调用我们的自定义提供者来完成任务。
总结
在本章中,我们看到,开发自定义提供者来管理成员资格和角色是非常方便的。你可以扩展应用来满足你的需要。你还可以添加更多的安全特征,比如加密和强密码。
源码下载: http://www.cnblogs.com/Files/z365days/providermodel3.zip