理解Asp.net 提供者模型(第3部分)
引言
在第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的成员资格类和角色类,这些类依次调用我们的自定义提供者来完成任务。
总结
在本章中,我们看到,开发自定义提供者来管理成员资格和角色是非常方便的。你可以扩展应用来满足你的需要。你还可以添加更多的安全特征,比如加密和强密码。
源码下载: https://files.cnblogs.com/z365days/providermodel3.zip
浙公网安备 33010602011771号