实现成员资格提供程序

更新:2007 年 11 月

ASP.NET 成员资格专为使您可以轻松地将多个不同的成员资格提供程序用于您的 ASP.NET 应用程序而设计。可以使用 .NET Framework 提供的成员资格提供程序,也可以实现自己的提供程序。

创建自定义成员资格提供程序主要有两个原因。

  • 需要将成员资格信息存储在一个 .NET Framework 内附的成员资格提供程序不支持的数据源中,如 FoxPro 数据库、Oracle 数据库或其他数据源。

  • 需要使用不同于 .NET Framework 附带的提供程序所使用的数据库架构来管理成员资格信息。一个常见的示例是公司或网站的 SQL Server 数据库中已有的成员资格数据。

必需的类

若要实现成员资格提供程序,请创建一个继承 System.Web.Security 命名空间的 MembershipProvider 抽象类的类。MembershipProvider 抽象类继承 System.Configuration.Provider 命令空间的 ProviderBase 抽象类,因此还必须实现 ProviderBase 类必需的成员。下表列出了必须从 ProviderBaseMembershipProvider 抽象类实现的必需的属性和方法,并提供了每个属性和方法的说明。若要查看每个成员的实现,请参见为示例成员资格提供程序的实现提供的代码。

必需的 ProviderBase 成员

成员

说明

Initialize 方法

采用提供程序的名称和配置设置的 NameValueCollection 作为输入。用于设置提供程序实例的属性值,包括特定于实现的值和在配置中提供的配置文件(Machine.config 或 Web.config)中指定的选项。

必需的 MembershipProvider 成员

成员

说明

EnablePasswordReset 属性

在配置文件 (Web.config) 中指定的 Boolean 值。

EnablePasswordReset 属性指示用户是否可以使用 ResetPassword 方法将其当前密码改写为随机生成的新密码。

此属性为只读。

EnablePasswordRetrieval 属性

在配置文件 (Web.config) 中指定的 Boolean 值。

EnablePasswordRetrieval 属性指示用户是否可以使用 GetPassword 方法取回其密码。

此属性为只读。

RequiresQuestionAndAnswer 属性

在配置文件 (Web.config) 中指定的 Boolean 值。

RequiresQuestionAndAnswer 属性指示用户是否必须提供一个密码提示问题答案,才能使用 GetPassword 方法取回其密码或使用 ResetPassword 方法重置其密码。

此属性为只读。

RequiresUniqueEmail 属性

在配置文件 (Web.config) 中指定的 Boolean 值。

RequiresUniqueEmail 属性指示用户在创建新用户时是否必须提供唯一的电子邮件地址。如果当前 ApplicationName 的数据源中已存在某一用户,则 CreateUser 方法返回 null(在 Visual Basic 中为 Nothing)和一个 DuplicateEmail 状态值。

此属性为只读。

PasswordFormat 属性

在配置文件 (Web.config) 中指定的 MembershipPasswordFormat 值。

PasswordFormat 属性指示存储密码的格式。密码可以采用 Clear、Encrypted 和 Hashed 密码格式存储。Clear 密码以纯文本格式存储,这可以提高存储和检索密码的性能,但安全性较差,当数据源安全性受到威胁时此类密码很容易被读取。Encrypted 密码在存储时进行了加密,可以在比较或检索密码时进行解密。此类密码在存储和检索时需要进行额外处理,但比较安全,在数据源的安全性受到威胁时不容易被获取。Hashed 密码在存储到数据库时使用单向哈希算法和随机生成的 salt 值进行了散列。在验证某一密码时,将用数据库中的 salt 值对该密码进行散列以进行验证。哈希密码不能检索。

可以使用 MembershipProvider 类的 EncryptPasswordDecryptPassword 虚方法加密和解密密码值,也可以提供自己的加密代码。如果使用 MembershipProvider 类的 EncryptPasswordDecryptPassword 虚方法,则使用配置中提供的 machineKey 元素(ASP.NET 设置架构)密钥信息加密 Encrypted 密码。

此属性为只读。

MaxInvalidPasswordAttempts 属性

在配置文件 (Web.config) 中指定的 Integer 值。

MaxInvalidPasswordAttemptsPasswordAttemptWindow 一起工作,防止不明来源反复尝试猜测成员资格用户的密码或密码提示问题答案。在 PasswordAttemptWindow 指定的分钟数内,如果为某一成员资格用户所输入的无效密码或密码提示问题答案的次数超过 MaxInvalidPasswordAttempts,则通过将 IsLockedOut 属性设置为 true 锁定该成员资格用户,直到使用 UnlockUser 方法解除对该用户的锁定。如果在达到 MaxInvalidPasswordAttempts 之前输入了有效密码或密码提示问题答案,则跟踪无效尝试次数的计数器将被重置为零。

如果 RequiresQuestionAndAnswer 属性设置为 false,则不跟踪输入无效密码提示问题答案的尝试次数。

输入无效密码和密码提示问题答案的尝试次数通过下面的方法进行跟踪:ValidateUserChangePasswordChangePasswordQuestionAndAnswerGetPasswordResetPassword 方法。

此属性为只读。

PasswordAttemptWindow 属性

在配置文件 (Web.config) 中指定的 Integer 值。

有关说明,请参见 MaxInvalidPasswordAttempts 属性的说明。

此属性为只读。

ApplicationName 属性

使用配置文件 (Web.config) 中指定的成员资格信息的应用程序的名称。ApplicationName 与相关用户信息一同存储在数据源中,并在查询这些信息时使用。有关更多信息,请参见本主题后面有关 ApplicationName 的部分。

如果未明确指定,则此属性为读/写,并且默认值为 ApplicationPath

CreateUser 方法

采用新用户名、密码和电子邮件地址作为输入,并将应用程序的新用户插入数据源中。CreateUser 方法返回一个用新创建用户的信息填充的 MembershipUser 对象。此外,CreateUser 方法还定义一个 out 参数(在 Visual Basic 中,可以使用 ByRef),该参数返回一个 MembershipCreateStatus 值,指示是否已成功创建用户,如创建失败则指明原因。

在已指定 MembershipValidatePasswordEventHandler 的条件下,CreateUser 方法会引发 ValidatingPassword 事件,并根据该事件的结果继续或取消用户创建操作。可使用 OnValidatingPassword 虚方法执行指定的 MembershipValidatePasswordEventHandler

UpdateUser 方法

采用以用户信息填充的 MembershipUser 对象作为输入,并用所提供的值更新数据源。

DeleteUser 方法

采用用户名作为输入,并从数据源删除该用户的信息。如果成功删除用户,则 DeleteUser 方法返回 true;否则,返回 false。所包含的另一个 Boolean 参数用于指示是否也删除该用户的角色或配置文件信息等相关信息。

ValidateUser 方法

采用用户名和密码作为输入,并验证这些值是否与数据源中的值相匹配。如果用户名和密码成功匹配,则 ValidateUser 方法返回 true;否则,返回 false。

GetUser 方法

采用唯一的用户标识符和一个Boolean 值(指示是否更新该用户的 LastActivityDate 值)作为输入,显示该用户当前是否联机。GetUser 方法返回一个用数据源中指定用户的当前值填充的 MembershipUser 对象。如果未在数据源中找到该用户名,则 GetUser 方法返回 null(在 Visual Basic 中为 Nothing)。

GetUser 方法

采用一个用户名和一个 Boolean 值(指示是否更新该用户的 LastActivityDate 值)作为输入,显示该用户当前是否联机。GetUser 方法返回一个用数据源中指定用户的当前值填充的 MembershipUser 对象。如果未在数据源中找到该用户名,则 GetUser 方法返回 null(在 Visual Basic 中为 Nothing)。

GetAllUsers 方法

返回一个用数据源中所有用户的 MembershipUser 对象填充的 MembershipUserCollection

GetAllUsers 返回的结果受 pageIndex 和 pageSize 参数的约束。pageSize 参数标识在 MembershipUserCollection 中返回的 MembershipUser 对象的最大数。pageIndex 参数标识要返回的结果页,1 标识第 1 页。totalRecords 参数是设置为成员资格用户总数的 out 参数。例如,如果应用程序有 13 个用户在数据库中,并且 pageIndex 值为 2,pageSize 为 5,则返回的 MembershipUserCollection 将包含返回的第 6 个到第 10 个用户。totalRecords 将设置为 13。

GetNumberOfUsersOnline 方法

如果 LastActivityDate 大于当前日期和时间减去 UserIsOnlineTimeWindow 属性值所得的值,则返回数据源中所有用户计数的整数值。UserIsOnlineTimeWindow 属性是一个整数值,用于指定在确定用户是否联机时使用的分钟数。

ResetPassword 方法

采用用户名和密码提示问题答案作为输入,为指定用户生成一个随机新密码。ResetPassword 方法用新密码值更新数据源中的用户信息,并将新密码作为一个 string 返回。用于生成随机密码的便捷机制是 Membership 类的 GeneratePassword 方法。

ResetPassword 方法可确保在执行任何操作之前都将 EnablePasswordReset 属性设置为 true。如果 EnablePasswordReset 属性为 false,则将引发 NotSupportedExceptionResetPassword 方法还会检查 RequiresQuestionAndAnswer 属性的值。如果 RequiresQuestionAndAnswer 属性为 true,则 ResetPassword 方法会对照数据源中存储的密码提示问题答案检查所输入的提示问题答案参数的值。如果它们不匹配,就引发 MembershipPasswordException

在已指定 MembershipValidatePasswordEventHandler 的条件下,ResetPassword 方法会引发 ValidatingPassword 事件以验证新生成的密码,并根据该事件的结果继续或取消密码重置操作。可使用 OnValidatingPassword 虚方法执行指定的 MembershipValidatePasswordEventHandler

GetPassword 方法

采用用户名和密码提示问题答案作为输入,并从数据源中检索该用户的密码,然后将该密码作为一个 string 返回。

GetPassword 可确保在执行任何操作之前都将 EnablePasswordRetrieval 属性设置为 true。如果 EnablePasswordRetrieval 属性为 false,则将引发 ProviderException

GetPassword 方法还会检查 RequiresQuestionAndAnswer 属性的值。如果 RequiresQuestionAndAnswer 属性为 true,则 GetPassword 方法会对照数据源中存储的密码提示问题答案检查所输入的提示问题答案参数的值。如果它们不匹配,就引发 MembershipPasswordException

GetUserNameByEmail 方法

采用电子邮件地址作为输入,并返回数据源中电子邮件地址与所提供的 email 参数值相匹配的第一个用户名。

如果未找到电子邮件地址匹配的用户名,则返回一个空字符串。

如果找到匹配特定电子邮地址的多个用户名,则只返回第一个找到的用户名。

ChangePassword 方法

采用用户名、当前密码和新密码作为输入,并在所提供的用户名和当前密码有效的情况下更新数据源中的密码。如果成功更新密码,则 ChangePassword 方法返回 true;否则,返回 false。

在已指定 MembershipValidatePasswordEventHandler 的条件下,ChangePassword 方法会引发 ValidatingPassword 事件,并根据该事件的结果继续或取消更改密码操作。可使用 OnValidatingPassword 虚方法执行指定的 MembershipValidatePasswordEventHandler

ChangePasswordQuestionAndAnswer 方法

采用用户名、密码、密码提示问题和密码提示问题答案作为输入,并在所提供的用户名和密码有效的情况下更新数据源中的密码提示问题和答案。如果成功更新密码提示问题和答案,则 ChangePasswordQuestionAndAnswer 方法返回 true;否则,返回 false。

如果所提供的用户名和密码无效,则返回 false。

FindUsersByName 方法

返回一个成员资格用户列表,其中的用户名与为所配置的 ApplicationName 提供的 usernameToMatch 匹配或部分匹配。例如,如果 usernameToMatch 参数设置为“user”,则返回诸如“user1”、“user2”、“user3”的用户。根据数据源提供通配符支持。根据用户名按字母顺序返回用户。

FindUsersByName 返回的结果受 pageIndex 和 pageSize 参数的约束。pageSize 参数标识在 MembershipUserCollection 中返回的 MembershipUser 对象的数目。pageIndex 参数标识要返回的结果页,1 标识第 1 页。totalRecords 参数是设置为与 usernameToMatch 值匹配的成员资格用户总数的 out 参数。例如,如果找到 13 个部分或整个用户名与 usernameToMatch 匹配的用户,并且 pageIndex 值为 2,pageSize 值为 5,则 MembershipUserCollection 将包含返回的第 6 个到第 10 个用户。totalRecords 将设置为 13。

FindUsersByEmail 方法

返回一个成员资格用户列表,其中的用户名与为所配置的 ApplicationName 提供的 emailToMatch 匹配或部分匹配。例如,如果 emailToMatch 参数设置为“address@example.com”,则返回具有诸如“address1@example.com”、“address2@example.com”等电子邮件地址的用户。根据数据源提供通配符支持。根据用户名按字母顺序返回用户。

FindUsersByEmail 返回的结果受 pageIndex 和 pageSize 参数的约束。pageSize 参数标识在 MembershipUserCollection 集合中返回的 MembershipUser 对象的数目。pageIndex 参数标识要返回的结果页,1 标识第 1 页。totalRecords 参数是设置为与 emailToMatch 值匹配成员资格用户总数的 out 参数。例如,如果找到 13 个部分或整个用户名与 emailToMatch 匹配的用户,并且 pageIndex 值为 2,pageSize 值为 5,则 MembershipUserCollection 将包含返回的第 6 个到第 10 个用户。totalRecords 将设置为 13。

UnlockUser 方法

采用用户名作为输入,将数据源中存储 IsLockedOut 属性的字段更新为 false。如果成功更新成员资格用户的记录,则 UnlockUser 方法返回 true;否则,返回 false。

ApplicationName

成员资格提供程序为每个应用程序单独存储用户信息。这允许多个 ASP.NET 应用程序使用相同数据源,而在创建重复用户名时不会发生冲突。或者,多个 ASP.NET 应用程序可以通过指定同一 ApplicationName 来使用同一用户数据源。

因为成员资格提供程序为每个应用程序单独存储用户信息,所以需要确保数据架构包含应用程序名,并确保查询和更新也包含应用程序名。例如,下面的命令用于根据电子邮件地址从数据库中检索用户名,并确保在查询中包括 ApplicationName

SELECT Username FROM MyUserTable 
  WHERE Email = 'someone@example.com' AND ApplicationName = 'MyApplication'

自定义成员

您可能需要用 ProviderBaseMembershipProvider 抽象类未能提供的附加功能来扩展成员资格提供程序接口。您添加到成员资格提供程序的任何公共成员都可以使用 Membership 类的 ProviderProviders 属性进行访问。

例如,将 IsLockedOut 属性设置为 true 的 LockUser 方法。下面的示例演示如何将 Provider 属性(该属性公开应用程序的默认成员资格提供程序)强制转换为自定义提供程序类型,以调用自定义 LockUser 方法。

Dim p As MyCustomProvider = CType(Membership.Provider, MyCustomProvider)
p.LockUser(username)
MyCustomProvider p = (MyCustomProvider)Membership.Provider;
p.LockUser(username);

线程安全

对于应用程序配置文件中指定的每个成员资格提供程序,ASP.NET 都会实例化单个成员资格提供程序实例,该实例用于 HttpApplication 对象所服务的所有请求。因此,可以有多个请求并发执行。ASP.NET 不保证对提供程序的调用的线程安全。因此需要编写线程安全的提供程序代码。例如,创建一个与数据库的连接或打开一个文件进行编辑,这些均应在被调用的成员(如 CreateUser)内完成,而不是在调用 Initialize 方法时打开文件或数据库连接。

请参见

概念

示例成员资格提供程序的实现

保证 ASP.NET 站点导航的安全

参考

ValidatePasswordEventArgs

OnValidatingPassword

其他资源

使用成员资格管理用户

保证 ASP.NET 网站的安全