.NET成员管理学习
成员资格介绍
ASP.NET 成员资格为您提供了一种验证和存储用户凭据的内置方法。 因此,ASP.NET 成员资格可帮助您管理网站中的用户身份验证。 您可以将 ASP.NET 成员资格与ASP.NET Forms 身份验证或 ASP.NET 登录控件一起使用以创建一个完整的用户身份验证系统。
ASP.NET 成员资格支持下列功能:
创建新用户和密码。
将成员资格信息(用户名、密码和支持数据)存储在 Microsoft SQL Server、Active Directory 或其他数据存储区。
对访问站点的用户进行身份验证。 可以以编程方式验证用户,也可以使用 ASP.NET 登录控件创建一个只需很少代码或无需代码的完整身份验证系统。
管理密码,包括创建、更改和重置密码。 根据您选择的成员资格选项不同,成员资格系统还可以提供一个使用用户提供的问题和答案的自动密码重置系统。
公开经过身份验证的用户的唯一标识,您可以在您自己的应用程序中使用该标识,也可以将该标识与 ASP.NET 个性化设置和角色管理(授权)系统集成。
指定自定义成员资格提供程序,这使您可以改为用自己的代码管理成员资格及在自定义数据存储区中维护成员资格数据
成员资格的工作原理
当我们在webconfig配置文件设置启用form验证后,通过在配置里面设置不受匿名访问的页面或者路径的时候。ASP.NET Forms 身份验证都会检查该用户是否经过身份验证,然后相应地允许该用户查看该页面或将用户重定向到登录页。在登录页面可以提示用户输入用户名和密码,然后调用验证方法进行验证。 在验证用户后,会生成一个加密并且含有特定标识的cookie,将其发送至客服端浏览器。在用户接下来的请求中都会将该cookie一起发送给服务端,通过对该cookie的判定实现只需要进行一次验证。
成员资格类
Membership :提供常规成员资格功能。这个类封装了成员资格提供的功能,如创建用户,删除用户,更新用户信息等等。个人认为Membership就类似于成员资格里面的bll层,我们知道用户的信息正常都是存储在数据库的,而该类中的功能是要与数据库打交道的。其DAL层的程序就是 SqlMemberShipProvider.这个是设计到提供程序模型
MemberShipUser:对象用于表示成员资格数据存储区中的单个成员资格用户。该对象公开有关成员资格用户的信息(如电子邮件地址),并为成员资格用户提供功能(如更改或重置其密码的功能)。
MembershipProvider:为可供成员资格系统使用的数据提供程序定义功能。(关于提供程序另外做介绍)
MembershipCreateStatus :提供描述性值,用于描述创建一个新成员资格用户时是成功还是失败。
MembershipPasswordFormat:指定 ASP.NET 包含的成员资格提供程序可以使用的密码存储格式(Clear、Hashed、Encrypted)。
提供程序模型
在某些情况下微软的成员资格提供程序SqlMemberShipProvider并不能满足我们的要求,因为SqlMemberShipProvider是通过ADO.NET对SQL数据库进行操作的。通过Reflector可以等到证实,下面的是SqlMemberShipProvider的创建用户CreateUser的核心代码:
当我们的数据库使用的Oracle或者我们是通过微软的企业库来访问数据库的时候,我们就必须自定义实现自己的SqlMemberShipProvider以供MemberShip使用。还是上面讲的MemberShip相当于BLL,这是我们DAL层(SqlMemberShipProvider)的访问方式要改变就必须重新实现DAL层。
1 connection = SqlConnectionHelper.GetConnection(this._sqlConnectionString, true);
2 this.CheckSchemaVersion(connection.Connection);
3 DateTime time = this.RoundToSeconds(DateTime.UtcNow);
4 SqlCommand command = new SqlCommand("dbo.aspnet_Membership_CreateUser", connection.Connection);
5 command.CommandTimeout = this.CommandTimeout;
6 command.CommandType = CommandType.StoredProcedure;
7 command.Parameters.Add(this.CreateInputParam("@ApplicationName", SqlDbType.NVarChar, this.ApplicationName));
8 command.Parameters.Add(this.CreateInputParam("@UserName", SqlDbType.NVarChar, username));
9 command.Parameters.Add(this.CreateInputParam("@Password", SqlDbType.NVarChar, objValue));
10 command.Parameters.Add(this.CreateInputParam("@PasswordSalt", SqlDbType.NVarChar, salt));
11 command.Parameters.Add(this.CreateInputParam("@Email", SqlDbType.NVarChar, email));
12 command.Parameters.Add(this.CreateInputParam("@PasswordQuestion", SqlDbType.NVarChar, passwordQuestion));
13 command.Parameters.Add(this.CreateInputParam("@PasswordAnswer", SqlDbType.NVarChar, str3));
14 command.Parameters.Add(this.CreateInputParam("@IsApproved", SqlDbType.Bit, isApproved));
15 command.Parameters.Add(this.CreateInputParam("@UniqueEmail", SqlDbType.Int, this.RequiresUniqueEmail ? 1 : 0));
16 command.Parameters.Add(this.CreateInputParam("@PasswordFormat", SqlDbType.Int, (int) this.PasswordFormat));
17 command.Parameters.Add(this.CreateInputParam("@CurrentTimeUtc", SqlDbType.DateTime, time));
18 SqlParameter parameter = this.CreateInputParam("@UserId", SqlDbType.UniqueIdentifier, providerUserKey);
19 parameter.Direction = ParameterDirection.InputOutput;
20 command.Parameters.Add(parameter);
21 parameter = new SqlParameter("@ReturnValue", SqlDbType.Int);
22 parameter.Direction = ParameterDirection.ReturnValue;
23 command.Parameters.Add(parameter);
24 command.ExecuteNonQuery();
25
在实现之前首先要明白MemberShip是怎么CreateUser的。通过Reflector可以看见MemberShip最后调用CreateUser是通过下面这句代码实现的
Provider.CreateUser(username, password, email, passwordQuestion, passwordAnswer, isApproved, providerUserKey, out status);
Provider的类型是MemberShipProvider是Membership的一个静态属性:
其中的Initialize()方法很重要,当然和很长,有一段很重要的代码:
public static MembershipProvider Provider{
get {
Initialize();
return s_Provider;
}
}
foreach (ProviderSettings settings in membership.Providers)
{
Type c = Type.GetType(settings.Type, true, true);
if (!typeof(MembershipProvider).IsAssignableFrom(c))
{
throw new ArgumentException(SR.GetString("Provider_must_implement_type", new object[] { typeof(MembershipProvider).ToString() }));
}
MembershipProvider provider = (MembershipProvider) Activator.CreateInstance(c);
NameValueCollection parameters = settings.Parameters;
NameValueCollection config = new NameValueCollection(parameters.Count, StringComparer.Ordinal);
foreach (string str2 in parameters)
{
config[str2] = parameters[str2];
}
provider.Initialize(settings.Name, config);
s_Providers.Add(provider);
}
可以看到这段代码的大致意思就是根据配置文件的配置,利用反射到动态生成我们需要自己设计的提供程序类。然后利用配置文件的配置信息,调用该类的初始化函数provider.Initialize 来初始化该类的相关信息。最后实现MemberShip s_Provider属性的设置。这里其实是抽象工程模式的一种应用,而Initialize是策略模式的一种实现。这两个的组合以及通过配置文件获得相关信息微软称之为Provider模式。 |
|