在 SQL Server 中创建成员身份架构 (C#)

作者 :Scott Mitchell

注意

自本文撰写以来,ASP.NET 成员资格提供程序已被 ASP.NET Identity 取代。 强烈建议更新应用以使用 ASP.NET 标识 平台,而不是本文撰写时介绍的成员资格提供程序。 ASP.NET 标识比 ASP.NET 成员身份系统具有许多优势,包括:

  • 性能更好
  • 改进了可扩展性和可测试性
  • 支持 OAuth、OpenID Connect 和双因素身份验证
  • 基于声明的标识支持
  • 更好地与 ASP.Net Core 的互操作性

下载代码下载 PDF

本教程首先研究将必要架构添加到数据库以使用 SqlMembershipProvider 的技术。 接下来,我们将检查架构中的关键表,并讨论其用途和重要性。 本教程最后介绍如何告诉 ASP.NET 应用程序成员资格框架应使用哪个提供程序。

简介

前两个教程介绍了如何使用表单身份验证来识别网站访问者。 借助表单身份验证框架,开发人员可以轻松地将用户登录到网站,并通过使用身份验证票证跨页面访问记住他们。 类 FormsAuthentication 包括用于生成票证并将其添加到访问者 Cookie 的方法。 FormsAuthenticationModule检查所有传入的请求,对于具有有效身份验证票证的请求,创建 和 FormsIdentity 对象并将其与当前请求相关联GenericPrincipal。 Forms 身份验证只是一种机制,用于在登录时向访问者授予身份验证票证,并在后续请求中分析该票证以确定用户的身份。 对于支持用户帐户的 Web 应用程序,我们仍然需要实现用户存储并添加功能来验证凭据、注册新用户以及大量与用户帐户相关的其他任务。

在 ASP.NET 2.0 之前,开发人员需要实现所有这些与用户帐户相关的任务。 幸运的是,ASP.NET 团队认识到了这一缺点,并在 ASP.NET 2.0 中引入了成员资格框架。 成员资格框架是.NET Framework中的一组类,提供用于完成核心用户帐户相关任务的编程接口。 此框架是在 提供程序模型之上构建的,该模型允许开发人员将自定义实现插入到标准化 API 中。

安全基础知识和 ASP.NET 支持教程中所述,.NET Framework附带两个内置成员资格提供程序: ActiveDirectoryMembershipProviderSqlMembershipProvider。 顾名思义, SqlMembershipProvider 使用 Microsoft SQL Server 数据库作为用户存储。 为了在应用程序中使用此提供程序,我们需要告诉提供程序要使用哪个数据库作为存储。 如您想象的那样, SqlMembershipProvider 预期用户存储数据库具有特定的数据库表、视图和存储过程。 我们需要将此预期的架构添加到所选数据库。

本教程首先研究将必要架构添加到数据库以使用 SqlMembershipProvider的方法。 接下来,我们将检查架构中的关键表,并讨论其用途和重要性。 本教程最后介绍如何告诉 ASP.NET 应用程序成员资格框架应使用哪个提供程序。

现在就开始吧!

步骤 1:确定用户存储的放置位置

ASP.NET 应用程序的数据通常存储在数据库中的多个表中。 实现数据库架构时, SqlMembershipProvider 必须决定是将成员资格架构放在与应用程序数据相同的数据库中,还是放在备用数据库中。

出于以下原因,我建议将成员资格架构定位到与应用程序数据相同的数据库中:

  • 可维护性 将数据封装在一个数据库中的应用程序比具有两个单独数据库的应用程序更易于理解、维护和部署。
  • 关系完整性 通过在与应用程序表相同的数据库中查找与成员资格相关的表,可以在与成员资格相关的表的主键与相关应用程序表之间建立 外键约束

仅当有多个应用程序(每个应用程序都使用单独的数据库,但需要共享一个通用的用户存储)时,将用户存储和应用程序数据分离到单独的数据库中才有意义。

创建数据库

自第二篇教程以来我们一直在构建的应用程序尚不需要数据库。 但是,用户存储现在需要一个。 让我们创建一个,然后将提供程序所需的 SqlMembershipProvider 架构添加到其中 (请参阅步骤 2) 。

注意

在本教程系列中,我们将使用 Microsoft SQL Server 2005 Express Edition 数据库来存储应用程序表和SqlMembershipProvider架构。 做出这一决定有两个原因:第一,由于其成本- 免费 - Express Edition 是 2005 SQL Server最易读的版本;第二,SQL Server 2005 Express Edition数据库可以直接放置在 Web 应用程序的App_Data文件夹,使它成为将数据库和 Web 应用程序打包在一个 ZIP 文件中并在没有任何特殊设置说明或配置选项的情况下重新部署它的压缩。 如果希望使用非 Express Edition 版本的 SQL Server,请随意学习。 步骤几乎完全相同。 该SqlMembershipProvider架构适用于 Microsoft SQL Server 2000 及更新版本的任何版本。

从解决方案资源管理器右键单击文件夹,App_Data然后选择“添加新项”。 (如果在项目中未看到文件夹App_Data,请右键单击解决方案资源管理器中的项目,选择“添加 ASP.NET 文件夹”,然后选择App_Data“) ”,从“添加新项”对话框中,选择添加名为 SecurityTutorials.mdf的新SQL 数据库。 在本教程中,我们将向 SqlMembershipProvider 此数据库添加架构;在后续教程中,我们将创建其他表来捕获应用程序数据。

将名为 SecurityTutorials.mdf 数据库的新SQL 数据库添加到 App_Data 文件夹

图 1:将新SQL 数据库命名SecurityTutorials.mdf数据库添加到App_Data文件夹 (单击以查看全尺寸图像)

将数据库添加到 App_Data 文件夹会自动将其包含在“数据库资源管理器”视图中。 (在 Visual Studio 的非 Express Edition 版本中,数据库资源管理器称为服务器资源管理器。) 转到数据库资源管理器并展开刚添加 SecurityTutorials 的数据库。 如果在屏幕上看不到“数据库资源管理器”,请转到“视图”菜单并选择“数据库资源管理器”,或按 Ctrl+Alt+S。 如图 2 所示, SecurityTutorials 数据库为空 - 它不包含表、视图和存储过程。

SecurityTutorials 数据库当前为空

图 2:数据库 SecurityTutorials 当前为空 (单击以查看全尺寸图像)

步骤 2:将SqlMembershipProvider架构添加到数据库

SqlMembershipProvider需要在用户存储数据库中安装一组特定的表、视图和存储过程。 可以使用 工具添加aspnet_regsql.exe这些必需的数据库对象。 此文件位于 %WINDIR%\Microsoft.Net\Framework\v2.0.50727\ 文件夹中。

注意

该工具 aspnet_regsql.exe 提供命令行功能和图形用户界面。 图形界面更加用户友好,我们将在本教程中介绍。 当需要自动添加 SqlMembershipProvider 架构时(例如在生成脚本或自动测试方案中),命令行接口非常有用。

该工具aspnet_regsql.exe用于向指定的SQL Server数据库添加或删除 ASP.NET 应用程序服务。 ASP.NET 应用程序服务包含 和 SqlRoleProviderSqlMembershipProvider架构,以及其他 ASP.NET 2.0 框架的基于 SQL 的提供程序的架构。 我们需要向工具提供两位信息 aspnet_regsql.exe

  • 是否要添加或删除应用程序服务,以及
  • 要从中添加或删除应用程序服务架构的数据库

在提示数据库使用时 aspnet_regsql.exe ,该工具要求我们提供数据库所在的服务器的名称、用于连接到数据库的安全凭据以及数据库名称。 如果使用非 Express Edition of SQL Server,则应已知道此信息,因为它是通过 ASP.NET 网页处理数据库时必须通过连接字符串提供的信息。 但是,在文件夹中使用SQL Server 2005 Express Edition数据库时,确定服务器和数据库App_Data名称会稍微复杂一些。

以下部分介绍为 文件夹中的 SQL Server 2005 Express Edition 数据库指定服务器和数据库名称的App_Data简单方法。 如果不使用 SQL Server 2005 Express Edition请随时跳到安装应用程序服务部分。

确定文件夹中SQL Server 2005 Express Edition数据库的服务器和数据库App_Data名称

若要使用该工具, aspnet_regsql.exe 我们需要知道服务器和数据库名称。 服务器名称为 localhost\InstanceName。 最有可能的是, InstanceNameSQLExpress。 但是,如果手动安装SQL Server 2005 Express Edition (即在安装 Visual Studio) 时未自动安装,则可能选择了其他实例名称。

确定数据库名称有点复杂。 文件夹中的数据库 App_Data 通常具有包含 全局唯一标识符 的数据库名称以及数据库文件的路径。 我们需要确定此数据库名称,以便通过 aspnet_regsql.exe添加应用程序服务架构。

确定数据库名称的最简单方法是通过SQL Server Management Studio对其进行检查。 SQL Server Management Studio提供了用于管理 SQL Server 2005 数据库的图形界面,但它不随 express Edition of SQL Server 2005 一起提供。 好消息是,你可以下载免费的 express Edition SQL Server Management Studio。

注意

如果你的桌面上还安装了非 Express Edition 版本的 SQL Server 2005,则可能安装了完整版本的 Management Studio。 可以使用完整版本来确定数据库名称,并按照下面针对 Express Edition 所述的相同步骤进行操作。

首先关闭 Visual Studio,确保关闭 Visual Studio 对数据库文件施加的任何锁。 接下来,启动SQL Server Management Studio并连接到localhost\InstanceName数据库进行SQL Server 2005 Express Edition。 如前所述,实例名称可能为 SQLExpress。 对于“身份验证”选项,请选择“Windows 身份验证”。

连接到 SQL Server 2005 Express Edition 实例

图 3:连接到SQL Server 2005 Express Edition实例 (单击以查看全尺寸图像)

连接到 SQL Server 2005 Express Edition 实例后,Management Studio 会显示数据库、安全设置、服务器对象等的文件夹。 如果展开“数据库”选项卡,将看到 SecurityTutorials.mdf 数据库 在数据库实例中注册 - 我们需要先附加数据库。

右键单击“数据库”文件夹,然后从上下文菜单中选择“附加”。 这将显示“附加数据库”对话框。 在此处,单击“添加”按钮,浏览到 SecurityTutorials.mdf 数据库,然后单击“确定”。 图 4 显示了选择数据库后“ SecurityTutorials.mdf 附加数据库”对话框。 图 5 显示了成功附加数据库后的 Management Studio 对象资源管理器。

附加SecurityTutorials.mdf数据库

图 4:附加 SecurityTutorials.mdf 数据库 (单击以查看全尺寸图像)

SecurityTutorials.mdf数据库显示在“数据库”文件夹中

图 5:数据库 SecurityTutorials.mdf 显示在“数据库”文件夹中 (单击以查看全尺寸图像)

如图 5 所示, SecurityTutorials.mdf 数据库的名称相当荒谬。 让我们将其更改为更令人难忘的 (,并更轻松地键入) 名称。 右键单击数据库,从上下文菜单中选择“重命名”,并将其重命名 SecurityTutorialsDatabase为 。 这不会更改文件名,只是数据库用来标识自身的名称SQL Server。

将数据库重命名为 SecurityTutorialsDatabase

图 6:将数据库重命名为 SecurityTutorialsDatabase (单击 以查看全尺寸图像)

此时,我们分别知道数据库文件的服务器和数据库名称 SecurityTutorials.mdflocalhost\InstanceNameSecurityTutorialsDatabase。 现在,我们已准备好通过 aspnet_regsql.exe 该工具安装应用程序服务。

安装应用程序服务

若要启动 aspnet_regsql.exe 该工具,请转到“开始”菜单,然后选择“运行”。 输入 %WINDIR%\Microsoft.Net\Framework\v2.0.50727\aspnet_regsql.exe 到文本框中,然后单击“确定”。 或者,你可以使用 Windows 资源管理器向下钻取到相应的文件夹,然后双击 aspnet_regsql.exe 该文件。 任一方法都将实现相同的结果。

aspnet_regsql.exe在不带任何命令行参数的情况下运行该工具会启动 ASP.NET SQL Server安装向导图形用户界面。 借助向导,可以轻松地在指定数据库上添加或删除 ASP.NET 应用程序服务。 向导的第一个屏幕(如图 7 所示)描述了该工具的用途。

使用 ASP.NET SQL Server安装向导创建添加成员资格架构

图 7:使用“ASP.NET SQL Server安装向导创建”添加成员身份架构 (单击以查看全尺寸映像)

向导中的第二步询问是添加还是删除应用程序服务。 由于我们要添加 所需的表、视图和存储过程SqlMembershipProvider,因此请选择“为应用程序服务配置SQL Server”选项。 稍后,如果要从数据库中删除此架构,请重新运行此向导,但改为选择“从现有数据库中删除应用程序服务信息”选项。

选择“为应用程序服务配置SQL Server”选项

图 8:选择“为应用程序服务配置SQL Server”选项 (单击以查看全尺寸图像)

第三步提示输入数据库信息:服务器名称、身份验证信息和数据库名称。 如果已按照本教程进行操作,并且已将 SecurityTutorials.mdf 数据库添加到 App_Data,将其 localhost\InstanceName附加到 ,并将其重命名为 SecurityTutorialsDatabase,请使用以下值:

  • 服务器:localhost\InstanceName
  • Windows 身份验证
  • 数据库:SecurityTutorialsDatabase

输入数据库信息

图 9:输入“数据库信息” (单击以查看全尺寸图像)

输入数据库信息后,单击“下一步”。 最后一步总结了将要执行的步骤。 单击“下一步”安装应用程序服务,然后单击“完成”以完成向导。

注意

如果使用 Management Studio 附加数据库并重命名数据库文件,请确保在重新打开 Visual Studio 之前分离数据库并关闭 Management Studio。 若要分离 SecurityTutorialsDatabase 数据库,请右键单击数据库名称,然后从“任务”菜单中选择“分离”。

完成向导后,返回到 Visual Studio 并导航到数据库资源管理器。 展开“表”文件夹。 应看到一系列表,其名称以前缀 aspnet_开头。 同样,可以在“视图”和“存储过程”文件夹下找到各种视图和存储过程。 这些数据库对象构成应用程序服务架构。 我们将在步骤 3 中检查特定于成员身份和角色的数据库对象。

已将各种表、视图和存储过程添加到数据库

图 10:已将各种表、视图和存储过程添加到数据库 (单击以查看全尺寸图像)

注意

该工具 aspnet_regsql.exe 的图形用户界面安装整个应用程序服务架构。 但是,从命令行执行 aspnet_regsql.exe 时,可以指定要安装的特定应用程序服务组件 (或删除) 。 因此,如果只想添加 和 提供程序所需的SqlMembershipProvider表、视图和存储过程,请从命令行运行aspnet_regsql.exeSqlRoleProvider 或者,可以手动运行 所使用的 aspnet_regsql.exeT-SQL 创建脚本的相应子集。 这些脚本位于 WINDIR%\Microsoft.Net\Framework\v2.0.50727\ 名称为 InstallCommon.sqlInstallMembership.sqlInstallRoles.sqlInstallProfile.sqlInstallSqlState.sql 等的 文件夹中。

此时,我们已创建了 所需的 SqlMembershipProvider数据库对象。 但是,我们仍然需要指示成员资格框架应使用 SqlMembershipProvider (而不是 ActiveDirectoryMembershipProvider) ,并且 SqlMembershipProvider 应使用 SecurityTutorials 数据库。 我们将在步骤 4 中了解如何指定要使用的提供程序以及如何自定义所选提供程序的设置。 但首先,让我们更深入地了解刚刚创建的数据库对象。

步骤 3:查看架构的核心表

在 ASP.NET 应用程序中使用成员资格和角色框架时,提供程序会封装实现详细信息。 在将来的教程中,我们将通过.NET Framework MembershipRoles 类来与这些框架进行交互。 使用这些高级 API 时,我们无需关注低级别的详细信息,例如执行哪些查询或由 SqlMembershipProviderSqlRoleProvider修改了哪些表。

鉴于此,我们可以放心地使用成员资格和角色框架,而无需浏览步骤 2 中创建的数据库架构。 但是,在创建表以存储应用程序数据时,我们可能需要创建与用户或角色相关的实体。 在应用程序数据表与步骤 2 中创建的表之间建立外键约束时,这有助于熟悉 SqlMembershipProviderSqlRoleProvider 架构。 此外,在某些极少数情况下,我们可能需要直接在数据库级别 (与用户和角色存储进行交互,而不是通过 MembershipRoles 类) 。

将用户存储分区到应用程序中

成员资格和角色框架的设计使单个用户和角色存储可以在许多不同的应用程序之间共享。 使用成员资格或角色框架的 ASP.NET 应用程序必须指定要使用的应用程序分区。 简言之,多个 Web 应用程序可以使用相同的用户和角色存储。 图 11 描述了划分为三个应用程序的用户和角色存储:HRSite、CustomerSite 和 SalesSite。 这三个 Web 应用程序各有其唯一的用户和角色,但它们都以物理方式将用户帐户和角色信息存储在同一数据库表中。

用户帐户可以跨多个应用程序进行分区

图 11:用户帐户可能跨多个应用程序分区 (单击以查看全尺寸映像)

aspnet_Applications 是定义这些分区的内容。 使用数据库存储用户帐户信息的每个应用程序都在此表中由一行表示。 该 aspnet_Applications 表有四列: ApplicationIdApplicationNameLoweredApplicationNameDescriptionApplicationIduniqueidentifier类型为 ,是表的主键;ApplicationName为每个应用程序提供唯一的友好名称。

其他与“成员身份”和“角色”相关的表链接回 ApplicationId 中的 aspnet_Applications字段。 例如, aspnet_Users 包含每个用户帐户记录的表具有 ApplicationId 外键字段;该表的 aspnet_Roles ditto。 ApplicationId这些表中的 字段指定用户帐户或角色所属的应用程序分区。

存储用户帐户信息

用户帐户信息存储在两个表中: aspnet_Usersaspnet_Membership。 该 aspnet_Users 表包含保存基本用户帐户信息的字段。 三个最相关的列是:

  • UserId
  • UserName
  • ApplicationId

UserId 是主键 (,类型 uniqueidentifier 为) 。 UserName 为 类型 nvarchar(256) ,并且与密码一起构成用户的凭据。 (用户的密码存储在 aspnet_Membership 表中。) ApplicationId 将用户帐户链接到 中的 aspnet_Applications特定应用程序。 和 ApplicationId 列上UserName存在复合UNIQUE约束。 这可确保在给定应用程序中,每个 UserName 都是唯一的,但它允许 UserName 在不同的应用程序中使用相同的用户名。

aspnet_Membership 表包含其他用户帐户信息,例如用户的密码、电子邮件地址、上次登录日期和时间等。 和 aspnet_Membership 表中的aspnet_Users记录之间存在一对一的对应关系。 此关系由 UserId 中的 aspnet_Membership字段确保,该字段充当表的主键。 aspnet_Users与表一样,aspnet_Membership包括一个ApplicationId将此信息绑定到特定应用程序分区的字段。

保护密码

密码信息存储在 aspnet_Membership 表中。 SqlMembershipProvider允许使用以下三种方法之一将密码存储在数据库中:

  • 清除 - 密码以纯文本形式存储在数据库中。 我强烈建议不要使用此选项。 如果数据库遭到入侵(无论是黑客发现后门,还是拥有数据库访问权限的不满员工)都会提供每个用户的凭据。
  • 哈希 - 使用单向哈希算法和随机生成的盐值对密码进行哈希处理。 此哈希值 (以及盐) 存储在数据库中。
  • 加密 - 密码的加密版本存储在数据库中。

使用的密码存储技术取决于 SqlMembershipProvider 中指定的 Web.config设置。 我们将在步骤 4 中介绍如何 SqlMembershipProvider 自定义设置。 默认行为是存储密码的哈希。

负责存储密码的列是 PasswordPasswordFormatPasswordSaltPasswordFormat 是类型的 int 字段,其值指示用于存储密码的方法:0 表示清除;1 表示哈希;2 表示加密。 PasswordSalt 分配随机生成的字符串,而不考虑使用的密码存储技术; PasswordSalt 的值仅在计算密码的哈希时使用。 最后,该 Password 列包含实际密码数据,无论是纯文本密码、密码哈希还是加密密码。

表 1 说明了在存储密码 MySecret 时,这三列对于各种存储技术可能是什么样子的! .

存储技术<_o3a_p /> 密码<_o3a_p /> PasswordFormat<_o3a_p /> PasswordSalt<_o3a_p />
清除 MySecret! 0 tTnkPlesqisc2y2SMEygA==
哈希 2oXm6sZHWbTHFgjgkGQsc2Ec9ZM= 1 wFgjUfhdUFOCKQiI61vtiQ==
加密 62RZgDvhxykkqsMchZ0Yly7HS6onhpaoCYaRxV8g0F4CW56OXUU3e7Inza9j9BKp 2 LSRzhGS/aa/oqAXGLHJNBw==

表 1:存储密码 MySecret 时 Password-Related 字段的示例值!

注意

使用 SqlMembershipProvider 的特定加密或哈希算法由 元素中的 <machineKey> 设置确定。

存储角色和角色关联

角色框架允许开发人员定义一组角色,并指定哪些用户属于哪些角色。 此信息通过两个表在数据库中捕获: aspnet_Rolesaspnet_UsersInRoles。 表中的每条记录 aspnet_Roles 都表示特定应用程序的角色。 与表 aspnet_Users 非常类似,该 aspnet_Roles 表有三个与讨论相关的列:

  • RoleId
  • RoleName
  • ApplicationId

RoleId 是主键 (,类型 uniqueidentifier 为) 。 RoleName 的类型为 nvarchar(256)。 并将 ApplicationId 用户帐户链接到 中的 aspnet_Applications特定应用程序。 和 ApplicationId 列存在复合UNIQUE约束RoleName,可确保在给定应用程序中每个角色名称都是唯一的。

aspnet_UsersInRoles 表充当用户和角色之间的映射。 只有两列和 UserIdRoleId ,它们共同构成复合主键。

步骤 4:指定提供程序并自定义其设置

支持提供程序模型的所有框架(例如成员资格和角色框架)本身缺乏实现详细信息,而是将该责任委托给提供程序类。 对于 Membership 框架, Membership 类定义用于管理用户帐户的 API,但它不直接与任何用户存储交互。 相反, Membership 类的方法将请求移交给配置的提供程序 - 我们将使用 SqlMembershipProvider。 调用 类中的 Membership 方法之一时,成员资格框架如何知道将调用委托给 SqlMembershipProvider

Membership 具有一个 Providers 属性 ,该属性包含对可供成员资格框架使用的所有已注册提供程序类的引用。 每个已注册的提供程序都有一个关联的名称和类型。 名称提供了一种用户友好的方式来引用集合中的 Providers 特定提供程序,而 类型标识提供程序类。 此外,每个已注册的提供程序可能包含配置设置。 成员资格框架的配置设置包括 passwordFormatrequiresUniqueEmail等。 有关 所使用的配置设置的完整列表, SqlMembershipProvider请参阅表 2。

属性 Providers 的内容是通过 Web 应用程序的配置设置指定的。 默认情况下,所有 Web 应用程序都有一个名为 AspNetSqlMembershipProvider 类型的 SqlMembershipProvider提供程序。 此默认成员身份提供程序在 machine.config 位于 %WINDIR%\Microsoft.Net\Framework\v2.0.50727\CONFIG)的 (中注册:

<membership>
 <providers>
 <add name="AspNetSqlMembershipProvider"
 type="System.Web.Security.SqlMembershipProvider, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" 
 connectionStringName="LocalSqlServer"
 enablePasswordRetrieval="false"
 enablePasswordReset="true"
 requiresQuestionAndAnswer="true"
 applicationName="/"
 requiresUniqueEmail="false"
 passwordFormat="Hashed"
 maxInvalidPasswordAttempts="5"
 minRequiredPasswordLength="7"
 minRequiredNonalphanumericCharacters="1"
 passwordAttemptWindow="10"
 passwordStrengthRegularExpression=""/>
 </providers> 
</membership>

如上述标记所示, <membership> 元素 定义成员资格框架的配置设置, <providers> 而子元素 指定已注册的提供程序。 可以使用 或 <add><remove> 元素添加或删除提供程序;使用 <clear> 元素可删除所有当前注册的提供程序。 如上述标记所示,machine.config添加类型为 的SqlMembershipProvider提供程序AspNetSqlMembershipProvider

除了 nametype 属性, <add> 元素还包含定义各种配置设置值的属性。 表 2 列出了可用的 SqlMembershipProvider特定于的配置设置,以及每个设置的说明。

注意

表 2 中记录的任何默认值都引用 类中 SqlMembershipProvider 定义的默认值。 请注意,中 AspNetSqlMembershipProvider 并非所有配置设置都对应于 类的 SqlMembershipProvider 默认值。 例如,如果未在成员资格提供程序中指定,则 requiresUniqueEmail 设置默认为 true。 但是, AspNetSqlMembershipProvider 通过显式指定值 false来替代此默认值。

设置<_o3a_p /> 说明<_o3a_p />
ApplicationName 回想一下,成员资格框架允许跨多个应用程序对单个用户存储进行分区。 此设置指示成员资格提供程序使用的应用程序分区的名称。 如果未显式指定此值,则会在运行时将其设置为应用程序的虚拟根路径的值。
commandTimeout 指定 SQL 命令超时值 () 秒。 默认值为 30。
connectionStringName 元素中<connectionStrings>用于连接到用户存储数据库的连接字符串的名称。 此值是必需的。
description 提供注册的提供程序的友好说明。
enablePasswordRetrieval 指定用户是否可以检索忘记的密码。 默认值为 false
enablePasswordReset 指示是否允许用户重置其密码。 默认为 true
maxInvalidPasswordAttempts 在指定 passwordAttemptWindow 用户被锁定之前,给定用户可能发生的最大登录尝试失败次数。默认值为 5。
minRequiredNonalphanumericCharacters 必须出现在用户密码中的非字母数字字符的最小数目。 此值必须介于 0 和 128 之间;默认值为 1。
minRequiredPasswordLength 密码中所需的最小字符数。 此值必须介于 0 和 128 之间;默认值为 7。
name 已注册的提供程序的名称。 此值是必需的。
passwordAttemptWindow 跟踪失败登录尝试的分钟数。 如果用户在此指定时段内提供无效的登录凭据 maxInvalidPasswordAttempts 时间,则会锁定这些凭据。默认值为 10。
PasswordFormat 密码存储格式: ClearHashedEncrypted。 默认为 Hashed
passwordStrengthRegularExpression 如果提供,则此正则表达式用于在创建新帐户或更改其密码时评估用户所选密码的强度。 默认值为空字符串。
requiresQuestionAndAnswer 指定用户在检索或重置其密码时是否必须回答其安全问题。 默认值为 true
requiresUniqueEmail 指示给定应用程序分区中的所有用户帐户是否必须具有唯一的电子邮件地址。 默认值为 true
type 指定提供程序的类型。 此值是必需的。

表 2:成员资格和 SqlMembershipProvider 配置设置

除了 AspNetSqlMembershipProvider,还可以通过向 文件添加类似的标记 Web.config 来逐个应用程序注册其他成员资格提供程序。

注意

角色框架的工作方式大致相同:中 machine.config 存在默认注册的角色提供程序,并且可以在 中 Web.config逐个应用程序自定义已注册的提供程序。 我们将在未来的教程中详细介绍角色框架及其配置标记。

自定义SqlMembershipProvider设置

默认 SqlMembershipProvider () 的 connectionStringName 属性设置为 LocalSqlServerAspNetSqlMembershipProvider 。 与提供程序一AspNetSqlMembershipProvider样,连接字符串名称LocalSqlServer在 中machine.config定义。

<connectionStrings> 
 <add name="LocalSqlServer" 
 connectionString="data source=.\SQLEXPRESS;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|aspnetdb.mdf;User Instance=true" 
 providerName="System.Data.SqlClient"/> 
</connectionStrings>

如你所看到的,此连接字符串定义了一个 SQL 2005 Express Edition 数据库,该数据库位于 |DataDirectory|aspnetdb.mdf'。 字符串 |DataDirectory |在运行时转换为指向 ~/App_Data/ 目录,因此数据库路径 |DataDirectory|aspnetdb.mdf“转换为 ~/App_Data/aspnet.mdf

如果未在应用程序的 Web.config 文件中指定任何成员资格提供程序信息,则应用程序将使用默认注册的成员资格提供程序 AspNetSqlMembershipProvider~/App_Data/aspnet.mdf如果数据库不存在,ASP.NET 运行时会自动创建它并添加应用程序服务架构。 但是,我们不想使用 aspnet.mdf 数据库;而是要使用 SecurityTutorials.mdf 在步骤 2 中创建的数据库。 可以通过以下两种方式之一完成此修改:

  • LocalSqlServer 指定值连接字符串名称Web.config通过覆盖 LocalSqlServer 中的Web.config连接字符串名称值,我们可以使用默认注册的成员资格提供程序 (AspNetSqlMembershipProvider) ,并使其与数据库正确配合使用SecurityTutorials.mdf。 如果你对 指定的 AspNetSqlMembershipProvider配置设置满意,则此方法很好。 有关此技术的详细信息,请参阅 Scott Guthrie 的博客文章配置 ASP.NET 2.0 应用程序服务以使用 SQL Server 2000 或 SQL Server 2005
  • 添加类型SqlMembershipProvider为 的新注册提供程序并配置connectionStringName设置为指向SecurityTutorials.mdf数据库。在想要自定义除数据库连接字符串之外的其他配置属性的情况下,此方法非常有用。 在我自己的项目中,我总是使用此方法,因为它的灵活性和可读性。

在添加引用SecurityTutorials.mdf数据库的新注册提供程序之前,我们首先需要在 的 Web.config节中添加适当的连接字符串值<connectionStrings>。 以下标记添加了一个名为 SecurityTutorialsConnectionString 的新连接字符串,该新连接字符串引用 文件夹中的 SQL Server 2005 Express Edition SecurityTutorials.mdf 数据库App_Data

<configuration>
 <connectionStrings>
 <add name="SecurityTutorialsConnectionString" 
 connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SecurityTutorials.mdf;Integrated Security=True;User Instance=True" 
 providerName="System.Data.SqlClient"/> 
 </connectionStrings> 
 <system.web>
 ... Configuration markup  removed for brevity ... 
 </system.web>
</configuration>

注意

如果使用备用数据库文件,请根据需要更新连接字符串。 有关形成正确连接字符串的详细信息,请参阅 ConnectionStrings.com

接下来,将以下成员资格配置标记添加到 Web.config 文件。 此标记注册名为 SecurityTutorialsSqlMembershipProvider的新提供程序。

<configuration> 
 <connectionStrings>
 <add name="SecurityTutorialsConnectionString" 
 connectionString="Data Source=.\SQLEXPRESS;AttachDbFilename=|DataDirectory|\SecurityTutorials.mdf;Integrated Security=True;User Instance=True" 
 providerName="System.Data.SqlClient"/>
 </connectionStrings> 
 <system.web>
 <membership defaultProvider="SecurityTutorialsSqlMembershipProvider">
 <providers>
 <!--Add a customized SqlMembershipProvider --> 
 <add name="SecurityTutorialsSqlMembershipProvider" 
 type="System.Web.Security.SqlMembershipProvider"
 connectionStringName="SecurityTutorialsConnectionString"
 enablePasswordRetrieval="false"
 enablePasswordReset="true"
 requiresQuestionAndAnswer="true"
 applicationName="SecurityTutorials"
 requiresUniqueEmail="true"
 passwordFormat="Hashed"
 maxInvalidPasswordAttempts="5"
 minRequiredPasswordLength="7"
 minRequiredNonalphanumericCharacters="1"
 passwordAttemptWindow="10"
 passwordStrengthRegularExpression=""/>
 </providers>
 </membership>
 ... Configuration markup removed for brevity ... 
 </system.web>
</configuration>

除了注册SecurityTutorialsSqlMembershipProvider提供程序之外,上述标记还通过defaultProvider元素) 中的 <membership> 属性将 定义为SecurityTutorialsSqlMembershipProvider默认提供程序 (。 回想一下,成员资格框架可以有多个已注册的提供程序。 由于 AspNetSqlMembershipProvider 在 中 machine.config注册为 的第一个提供程序,因此除非我们另有说明,否则它将充当默认提供程序。

目前,我们的应用程序有两个已注册的提供程序: AspNetSqlMembershipProviderSecurityTutorialsSqlMembershipProvider。 但是,在注册SecurityTutorialsSqlMembershipProvider提供程序之前,我们可以通过紧挨在 元素前面<add>添加 元素<clear />来清除所有以前注册的提供程序。 这会从已注册的提供程序列表中清除 AspNetSqlMembershipProvider ,这意味着 SecurityTutorialsSqlMembershipProvider 将是唯一已注册的成员资格提供程序。 如果使用此方法,则无需将 标记为 SecurityTutorialsSqlMembershipProvider 默认提供程序,因为它是唯一已注册的成员资格提供程序。 有关使用 <clear />的详细信息,请参阅在添加提供程序时使用 <clear />

请注意, SecurityTutorialsSqlMembershipProviderconnectionStringName 设置引用刚添加SecurityTutorialsConnectionString连接字符串名称,并且其applicationName设置已设置为 SecurityTutorials 的值。 此外, requiresUniqueEmail 设置已设置为 true。 所有其他配置选项都与 中的 AspNetSqlMembershipProvider值相同。 如果需要,可在此处随意进行任何配置修改。 例如,可以通过要求两个非字母数字字符(而不是一个)或将密码长度增加到 8 个字符而不是 7 个字符来收紧密码强度。

注意

回想一下,成员资格框架允许跨多个应用程序对单个用户存储进行分区。 成员资格提供程序的设置 applicationName 指示提供程序在使用用户存储时使用的应用程序。 请务必显式设置 applicationName 配置设置的值,因为如果未 applicationName 显式设置 ,则会在运行时将其分配给 Web 应用程序的虚拟根路径。 只要应用程序的虚拟根路径不更改,这就可以正常工作,但如果将应用程序移动到其他路径,设置 applicationName 也会更改。 发生这种情况时,成员资格提供程序将开始使用与以前使用的应用程序分区不同的应用程序分区。 在移动之前创建的用户帐户将驻留在不同的应用程序分区中,这些用户将无法再登录到站点。 有关此问题的更深入讨论,请参阅 配置 ASP.NET 2.0 成员资格和其他提供程序时始终设置 applicationName 属性

总结

此时,我们有一个数据库,其中包含配置的应用程序服务 (SecurityTutorials.mdf) ,并配置了 Web 应用程序,以便成员资格框架使用我们刚刚注册的 SecurityTutorialsSqlMembershipProvider 提供程序。 此注册的提供程序的类型SqlMembershipProvider为 ,其connectionStringName设置为相应的连接字符串 (SecurityTutorialsConnectionString) 并显式设置其applicationName值。

现在,我们已准备好使用应用程序中的成员资格框架。 在下一教程中,我们将了解如何创建新的用户帐户。 接下来,我们将探讨如何对用户进行身份验证、执行基于用户的授权,以及将其他用户相关信息存储在数据库中。

编程愉快!

深入阅读

有关本教程中讨论的主题的详细信息,请参阅以下资源:

有关本教程中包含的主题的视频培训

关于作者

Scott Mitchell 是多本 ASP/ASP.NET 书籍的作者,4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0自学。 可在 上或通过他的博客http://ScottOnWriting.NET联系 mitchell@4guysfromrolla.com Scott。

特别感谢

本教程系列由许多有用的审阅者查看。 本教程的首席审阅者是 Alicja Maziarz。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处放置一行 mitchell@4GuysFromRolla.com