Membership

Microsoft

注意

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

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

ASP.NET 成员资格基于 ASP.NET 1.x 中的 Forms 身份验证模型的成功。 ASP.NET Forms 身份验证提供了一种便捷的方式,可以将登录表单合并到 ASP.NET 应用程序中,并针对数据库或其他数据存储验证用户。

ASP.NET 成员资格基于 ASP.NET 1.x 中的 Forms 身份验证模型的成功。 ASP.NET Forms 身份验证提供了一种便捷的方式,可以将登录表单合并到 ASP.NET 应用程序中,并针对数据库或其他数据存储验证用户。 FormsAuthentication 类的成员可以处理 Cookie 进行身份验证、检查有效登录、注销用户等。但是,在 ASP.NET 1.x 应用程序中实现 Forms 身份验证可能需要大量代码。

ASP.NET 2.0 中的成员身份是单独使用 Forms 身份验证的主要改进。 (与 Forms 身份验证结合使用时,成员身份最可靠,但使用 Forms 身份验证不是一项要求。) 正如你即将看到的,你可以使用 ASP.NET 2.0 中的 ASP.NET 成员资格和登录控件来实现功能强大的成员身份系统,而无需编写太多代码。

在 ASP.NET 2.0 中实现成员资格

成员资格是通过以下四个步骤实现的。 请记住,涉及许多子步骤以及也可以实现的可选配置。 这些步骤旨在说明配置成员身份的大局。

  1. 如果SQL Server用作成员资格存储,请创建成员资格数据库 (。)

  2. 在应用程序配置文件中指定成员资格选项。 默认启用 (成员身份。)

  3. 确定要使用的成员资格存储的类型。 选项包括:

    • Microsoft SQL Server (7.0 或更高版本)
    • Active Directory 存储
    • 自定义成员资格提供程序
  4. 为 ASP.NET Forms 身份验证配置应用程序。 同样,成员身份旨在利用 Forms 身份验证,但不需要使用 Forms 身份验证。

  5. 定义用户帐户以加入成员身份,并根据需要配置角色。

创建成员资格数据库

如果使用 SQL Server 7.0 或更高版本作为成员资格存储,则可以从 Visual Studio .NET 2005 命令提示符) 最轻松地使用 aspnet_regsql 实用工具 (来配置数据库。 aspnet_regsql 实用工具可用作命令提示符工具或通过 GUI 向导使用。 向导方法是配置数据库的最简单方法。 若要访问向导,只需运行以下命令:

aspnet_regsql W

运行该命令后,将显示 ASP.NET SQL Server安装向导,如下所示。

显示 A S P 点 NET S Q L 服务器安装向导的屏幕截图。

图 1

ASP.NET SQL Server安装向导会在向导中指定的实例中创建网站。 但是,ASP.NET 将使用machine.config文件中的连接字符串连接到数据库。 默认情况下,此连接字符串将指向 SQL Server 2005 实例,因此,如果使用 SQL Server 2000 或 SQL Server 7.0 实例,则需要修改 machine.config 文件中的连接字符串。 该连接字符串可位于此处:

<configuration>
    <connectionStrings>
      <add name="LocalSqlServer"
         connectionString="data source=(local);
         Integrated Security=SSPI;Initial Catalog=aspnetdb;"  
         providerName="System.Data.SqlClient" />
    </connectionStrings>
</configuration>

遗憾的是,如果不修改连接字符串,ASP.NET 不会提供描述性错误。 它只会继续抱怨说你尚未创建数据库。 在上述情况下,我已将连接字符串修改为指向本地 SQL Server 2000 实例。

指定配置并添加用户和角色

配置成员身份的下一步是将必要信息添加到应用程序的 web.config 文件中。 在 ASP.NET 1.x 中,由于使用 lowerCamelCase 和缺少 Intellisense,修改 web.config 文件有时很困难。 Visual Studio .NET 2005 使用用于配置文件的 Intellisense 使任务更加容易,但 ASP.NET 2.0 提供了用于编辑配置文件的 Web 界面,从而更进一步。

可以通过单击解决方案资源管理器工具栏上的“ASP.NET 配置”按钮来启动 Web 界面,如下所示。 还可以通过插入登录控件时显示的弹出窗口启动 Web 界面。

显示选中web.config的解决方案资源管理器工具栏的屏幕截图。

图 2

这会启动如下所示的 ASP.NET 网站管理工具。 ASP.NET 网站管理是一个四选项卡界面,可轻松管理应用程序设置。 以下选项卡可用:

  • 主页
  • 安全 配置用户、角色和访问权限。
  • 应用 配置应用程序设置。
  • 供应商 配置并测试应用程序成员资格提供程序。

使用网站管理工具,可以轻松创建新用户、创建新角色以及管理用户和角色。 此功能在 Windows 界面中不可用。 Windows 界面允许你轻松定义授权设置,以及添加、删除和管理网站管理工具中未包含的提供程序功能。

若要启动 Windows 界面,请打开 Internet Information Services 管理单元,右键单击应用程序,然后选择“属性”。 单击“ASP.NET”选项卡,然后单击“编辑配置”按钮。 (应用程序必须在 ASP.NET 2.0 下运行,才能启用“编辑配置”按钮。还可以在“ASP.NET”对话框中配置 ASP.NET 版本。) “ASP.NET 配置设置”对话框如下所示。

显示“A S P 点 N E T 配置设置”对话框中的“常规”选项卡的屏幕截图。

图 3

在“常规”选项卡上,列出了连接字符串和应用程序设置。 任何斜体设置都是在父配置文件中定义的, (machine.config或更高级别的web.config) ,不以斜体表示的设置都来自应用程序配置文件。 如果在应用程序级别添加、删除或编辑设置,ASP.NET 将在应用程序级别添加、删除或修改设置web.config,而不是从继承设置的配置文件中删除设置。

“身份验证”选项卡如下所示。 这是配置成员资格设置的位置。 可以在此处配置表单身份验证设置、成员资格提供程序和角色提供程序。

显示“A S P 点 N E T 配置”对话框中的“身份验证”选项卡的屏幕截图。

图 4

在应用程序中实现成员身份

在应用程序中实现 ASP.NET 2.0 成员身份的最简单方法是使用提供的登录控件。 此方法允许你实现 ASP.NET 2.0 成员身份的基础知识,而无需编写任何代码。

ASP.NET 2.0 中提供了以下登录控件:

登录控件

Login 控件为某人提供了一个接口,用于登录到你的成员资格系统。 它提供用户名和密码文本框以及登录按钮。 许多其他常见功能,例如为尚未注册的用户提供的链接、允许用户在后续访问中自动登录的复选框、密码提醒的链接等。Login 控件的所有功能都可以通过 控件的属性进行自定义。

在 ASP.NET 1.x 中,开发人员在使用 Forms 身份验证时必须编写相当数量的代码来执行查找。 使用 ASP.NET 2.0 成员身份,无需编写任何代码即可验证用户。 ASP.NET 将自动为你执行用户查找。 (如果在不使用 ASP.NET 成员身份的情况下使用 Login 控件,则可以使用 OnAuthenticate 方法来验证 user.)

LoginView 控件

LoginView 控件是默认提供两个模板的模板化控件;AnonymousTemplate 和 LoggedInTemplate。 显示的模板取决于用户是否已登录到你的成员资格系统。 此控件通常用于在用户尚未登录时显示 Login 控件,在用户登录时显示 LoginStatus 控件和/或其他登录控件。 如果在 ASP.NET 应用程序中使用角色管理,则 LoginView 控件可以根据用户角色显示特定模板。 (稍后将详细介绍 ASP.NET 角色管理。)

PasswordRecovery 控件

PasswordRecovery 控件允许用户接收包含其当前密码的电子邮件或重置其密码。 可以恢复明文和加密密码,并通过电子邮件发送给用户。 如果密码经过哈希处理,则无法恢复。 相反,用户需要执行密码重置。

LoginStatus 控件

LoginStatus 控件用于向未登录的用户显示登录指示器,向当前登录的用户显示注销指示器。 Request.IsAuthenticated 属性用于确定要显示的指示器。 LoginStatus 控件显示的指示器可以是通过 LoginTextLogoutText 属性) (实现的文本,也可以是通过 LoginImageUrlLogoutImageUrl 属性 (实现的图像。)

当用户通过 LoginStatus 控件注销时,他或她将重定向到 LogoutPageUrl 属性指定的 URL。 如果未设置该属性,则会刷新当前页。 由于网站可能受 Forms 身份验证保护,因此刷新当前页会将用户重定向到网站的登录页。

LoginName 控件

LoginName 控件显示当前登录到站点的用户的用户名。

CreateUserWizard 控件

CreateUserWizard 控件为用户提供了注册成员资格系统的便捷方法。 可以通过下面所示的 接口添加 (实现的步骤作为 WizardSteps) 的集合。

显示“创建用户向导任务”对话框的屏幕截图,其中包含用于注册新帐户的下拉菜单。

图 5

CreateUserWizard 是派生自 Wizard 类的模板化控件,提供以下模板:

  • HeaderTemplate 此模板控制向导标头的外观。
  • SidebarTemplate 此模板控制向导边栏的外观。
  • StartNavigationTemplate 此模板控制向导在开始步骤时导航的外观。
  • StepNavigationTemplate 此模板控制不在开始或完成步骤中时导航区域的外观。
  • FinishNavigationTemplate 此模板控制完成步骤时导航区域的外观。

此外,对于添加到向导的每个步骤,ASP.NET 将创建一个自定义模板,其中包含该步骤的 ContentTemplate 和 CustomNavigationTemplate。 有关自定义 CreateUserWizard 的完整详细信息,请参阅 VS.NET 2005 文档:

ChangePassword 控件

ChangePassword 控件允许用户更改其密码。 如果 DisplayUserName 属性为 true (默认情况下为 false) ,则用户可以在未登录时更改其密码。 如果用户已登录,并且 DisplayUserName 属性为 true,则用户将能够更改未登录的其他用户的密码,前提是他们知道该用户的用户 ID。

请记住,如果希望用户能够在无需登录的情况下更改密码,则需要确保显示 ChangePassword 控件的页面允许匿名访问。 显然,用户必须提供其旧密码才能更改其密码。

角色管理

通过角色管理,可以将用户分配到特定角色,然后根据该角色限制对特定文件或文件夹的访问。 角色管理还提供了一个 API,以便你可以以编程方式确定某人角色或确定特定角色中的所有用户并相应地做出响应。

角色管理不是 ASP.NET 成员身份的要求,也是使用角色管理的要求。 但是,这两者可以很好地相互补充,开发人员可能会将它们结合使用。

若要在应用程序中启用角色管理,请在 web.config 文件中进行以下更改:

<roleManager enabled="true" cacheRolesInCookie="true" cookieProtection="All" />

cacheRolesInCookie 属性设置为 true 时,ASP.NET 在客户端上的 Cookie 中缓存用户角色成员身份。 这样,无需调用 RoleProvider 即可进行角色查找。 使用此属性时,建议开发人员确保 cookieProtection 属性设置为 All。 (这是默认设置。) 这可确保对 Cookie 数据进行加密,并有助于确保 Cookie 内容未被更改。 可以使用网站管理工具添加角色。 它允许你轻松定义角色、根据这些角色配置对站点部分的访问权限,以及将用户分配到角色。

显示带有“添加角色”按钮的 A S P 点 N E T 网站管理工具的屏幕截图。

图 6

如上所示,只需输入角色的名称并单击“添加角色”即可添加新角色。 可以通过单击现有角色列表中的相应链接来管理或删除现有角色。

管理角色时,可以添加或删除用户,如下所示。

显示带有“查找用户”按钮的 A S P 点 N E T 网站管理工具的屏幕截图。

图 7

通过选中“用户处于角色中”复选框,可以轻松地将用户添加到特定角色。 ASP.NET 将使用相应的条目自动更新成员资格数据库。 还需要为应用程序配置访问规则。 ASP.NET 1.x 开发人员熟悉通过 web.config 文件中的 <authorization> 元素执行此操作,并且该选项在 ASP.NET 2.0 中仍然可用。 但是,它更易于使用网站管理工具管理访问规则,如下所示。

显示“A S P 点 N E T 网站管理工具”的屏幕截图,其中在“用户和角色”下选择了项。

图 8

在这种情况下,“管理”文件夹突出显示 (难以查看,因为该工具以浅灰色) 突出显示它,并且管理员角色已被授予访问权限。 拒绝所有其他用户。 可以单击头部图标以选择规则,然后使用“上移”和“下移”按钮排列规则。 与 ASP.NET <授权> 元素一样,规则按其出现的顺序进行处理。 换句话说,如果上述快照中的规则顺序被颠倒,则任何人都无权访问“管理”文件夹,因为 ASP.NET 遇到的第一个规则是拒绝所有人访问该文件夹的规则。

ASP.NET 2.0 会将web.config文件添加到要为其指定访问规则的文件夹。 可以通过配置文件或网站管理工具编辑访问规则。 换句话说,网站管理工具只是一个界面,可通过该接口在用户友好的环境中编辑配置文件。

在代码中使用角色

自版本 1.x 以来,用于角色管理的 API 没有更改。 IsInRole 方法用于确定用户是否处于特定角色。

if (User.IsInRole(Administrators)) {
    btnManageSite.Visible = true;
}

ASP.NET 还会创建 RolePrincipal 实例作为当前上下文的成员。 RolePrincipal 对象可用于获取用户所属的所有角色,如下所示:

string[] userRoles = ((RolePrincipal)User).GetRoles();

将 RoleGroups 与 LoginView 控件配合使用

了解角色管理和成员身份后,让我们简要讨论一下 LoginView 控件在 ASP.NET 2.0 中如何利用此功能。 如前所述,LoginView 控件是默认包含两个模板的模板化控件;AnonymousTemplate 和 LoggedInTemplate。 “LoginView 任务”对话框中有一个链接 (如下所示) ,可用于编辑 RoleGroups。

显示“登录视图任务”对话框中的“登录视图”控件的屏幕截图,其中选择了下拉列表和“角色组”。

图 9

每个 RoleGroup 对象都包含一个字符串数组,这些字符串定义 RoleGroup 应用于的角色。 若要将新的 RoleGroup 添加到 LoginView 控件,请单击“编辑 RoleGroups”链接。 在上图中,可以看到我为管理员添加了新的 RoleGroup。 通过从“视图”下拉列表中选择该 RoleGroup (RoleGroup[0]) ,可以配置仅向管理员角色成员显示的模板。 在下图中,我添加了一个新的 RoleGroup,该角色适用于销售角色和分发角色的成员。 这会向 LoginView 任务对话框中的“视图”下拉列表添加第二个 RoleGroup,添加到该模板的任何内容都将由“销售”或“分发”角色中的任何用户看到。

显示“角色组集合编辑器”对话框的屏幕截图,其中包含选择“管理员”的下拉列表。

图 10

重写现有成员资格提供程序

可通过多种方式扩展 ASP.NET 成员身份的功能。 首先,通过从 SqlMembershipProvider 类继承并重写其方法,可以明显地更改 SqlMembershipProvider 类的现有功能。 例如,如果要在创建用户时实现自己的功能,则可以创建自己的类,该类继承自 SqlMembershipProvider,如下所示:

public class jForumMembershipProvider : SqlMembershipProvider {
    public jForumMembershipProvider() {

    }
    public override MembershipUser CreateUser(
    string username,
    string password,
    string email,
    string passwordQuestion,
    string passwordAnswer,
    bool isApproved,
    object providerUserKey,
    out MembershipCreateStatus status) {
        // your own implementation
        return base.CreateUser(
        username,
        password,
        email,
        passwordQuestion,
        passwordAnswer,
        isApproved,
        providerUserKey,
        out status);
    }
}

另一方面,如果要创建自己的提供程序 (将成员身份信息存储在 Access 数据库中(例如) ),则可以创建自己的提供程序。

创建自己的成员资格提供程序

若要创建自己的成员资格提供程序,首先需要创建继承自 MembershipProvider 类的类。 如果使用 VB.NET,Visual Studio 2005 将为需要重写的所有方法添加存根。 如果使用 C#,请由你来添加存根。

需要重写以下内容:

  • ApplicationName 属性
  • ChangePassword 函数
  • ChangePasswordQuestionAndAnswer 函数
  • CreateUser 函数
  • DeleteUser 函数
  • EnablePasswordReset 属性
  • EnablePasswordRetrieval 属性
  • FindUsersByEmail 函数
  • FindUsersByName 函数
  • GetAllUsers 函数
  • GetNumberOfUsersOnline 函数
  • GetPassword 函数
  • GetUser 函数
  • GetUserNameByEmail 函数
  • MaxInvalidPasswordAttempts 属性
  • MinRequiredNonAlphanumericCharacters 属性
  • MinRequiredPasswordLength 属性
  • PasswordAttemptWindow 属性
  • PasswordFormat 属性
  • PasswordStrengthRegularExpression 属性
  • RequiresQuestionAndAnswer 属性
  • RequiresUniqueEmail 属性
  • ResetPassword 函数
  • 解锁用户函数
  • UpdateUser 函数
  • ValidateUser 函数

这是一个相当一个要作为 C# 开发人员实现的列表。 你可能会发现,在不使用任何实现的情况下在 VB.NET 中创建 类,然后使用 .NET 反射器或类似工具将代码转换为 C# 更容易。

连接字符串和其他属性应在 Initialize 方法中设置为其默认值。 (在 runtime.) Initialize 方法的第二个参数的类型为 System.Collections.Specialized.NameValueCollection,是对 <> add 元素的引用,该元素与web.config文件中的自定义提供程序相关联。 该条目如下所示:

<system.web>
  <authentication mode="Forms"/>
  <membership
  defaultProvider="jForumCustomMembershipProvider" >
    <providers>
      <add name="jForumCustomMembershipProvider"
      type="jForumCustomMembershipProvider"
      requiresQuestionAndAnswer="true"
      connectionString="Provider=Microsoft.Jet.
        OLEDB.4.0;Data Source=C:\jForumCustomMembershipProvider\
        App_Data\Members.mdb;Persist Security
        Info=False"
        />
    </providers>
  </membership>
</system.web>

下面是 Initialize 方法的示例。

public override void Initialize(string name,
    System.Collections.Specialized.NameValueCollection config) {

    if (config["requiresQuestionAndAnswer"])
        _requiresQuestionAndAnswer = true;
    _connString = config["connectionString"];
    base.Initialize(name, config);
}

为了在用户提交登录表单时对其进行验证,需要使用 ValidateUser 方法。 当用户单击 Login 控件中的登录按钮时,将触发此方法。 你将在此方法中放置执行用户查找的代码。

如你所看到的,编写自己的成员资格提供程序并不困难,并允许你扩展 ASP.NET 2.0 的这一强大功能。