配置使用应用程序服务的网站 (C#)

作者 :Scott Mitchell

注意

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

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

ASP.NET 版本 2.0 引入了一系列应用程序服务,这些服务是.NET Framework的一部分,可用作一套构建基块服务,可用于向 Web 应用程序添加丰富的功能。 本教程探讨如何在生产环境中配置网站以使用应用程序服务,并解决在生产环境中管理用户帐户和角色的常见问题。

简介

ASP.NET 版本 2.0 引入了一系列应用程序服务,这些服务是.NET Framework的一部分,可用作一套构建基块服务,可用于向 Web 应用程序添加丰富的功能。 应用程序服务包括:

  • 成员身份 - 用于创建和管理用户帐户的 API。
  • 角色 - 用于将用户分类为组的 API。
  • 配置文件 - 用于存储特定于用户的自定义内容的 API。
  • 站点地图 - 一种 API,用于以层次结构的形式定义站点的逻辑结构,然后可以通过导航控件(如菜单和痕迹导航)显示。
  • 个性化 - 用于维护自定义首选项的 API,最常与 Web 部件一起使用。
  • 运行状况监视 - 用于监视正在运行的 Web 应用程序的性能、安全性、错误和其他系统运行状况指标的 API。

应用程序服务 API 不绑定到特定实现。 相反,你指示应用程序服务使用特定的 提供程序,并且该提供程序使用特定技术实现该服务。 Web 托管公司托管的基于 Internet 的 Web 应用程序的最常用的提供程序是使用SQL Server数据库实现的提供程序。 例如, SqlMembershipProvider 是成员资格 API 的提供程序,用于将用户帐户信息存储在 Microsoft SQL Server 数据库中。

使用应用程序服务和SQL Server提供程序会在部署应用程序时增加一些挑战。 对于初学者,必须在开发和生产数据库上正确创建应用程序服务数据库对象,并相应地初始化。 还需要进行重要的配置设置。

注意

应用程序服务 API 是使用 提供程序模型设计的,这种设计模式允许在运行时提供 API 的实现详细信息。 .NET Framework附带了许多可以使用的应用程序服务提供程序,例如 SqlMembershipProviderSqlRoleProvider,它们是使用SQL Server数据库实现的成员资格和角色 API 的提供程序。 还可以创建和插入自定义提供程序。 事实上,Book Reviews Web 应用程序已包含站点地图 API (ReviewSiteMapProvider) 的自定义提供程序,该提供程序基于数据库中 的 和 Books 表中的数据Genres构造站点地图。

本教程首先介绍如何扩展 Book Reviews Web 应用程序以使用成员资格和角色 API。 然后,介绍如何部署一个 Web 应用程序,该应用程序使用具有SQL Server数据库实现的应用程序服务,最后解决在生产环境中管理用户帐户和角色的常见问题。

汇报书评应用程序

在过去的几个教程中,Book Reviews Web 应用程序已从静态网站更新为动态的数据驱动的 Web 应用程序,其中包含一组用于管理流派和评论的管理页面。 但是,此管理部分当前不受保护 - 任何知道管理页面 URL (或猜测) 的用户都可以在我们的网站上创建、编辑或删除评论。 保护网站某些部分的常见方法是实现用户帐户,然后使用 URL 授权规则限制对某些用户或角色的访问。 本教程中可供下载的 Book Reviews Web 应用程序支持用户帐户和角色。 它具有一个名为 管理员 定义的角色,只有此角色中的用户可以访问管理页。

注意

我在 Book Reviews Web 应用程序中创建了三个用户帐户:Scott、Jisun 和 Alice。 这三个用户都有相同的密码:password!斯科特和吉松是管理员角色,爱丽丝不是。 匿名用户仍可访问站点的非管理页面。 也就是说,无需登录即可访问站点,除非你想要对其进行管理,在这种情况下,必须以管理员角色中的用户身份登录。

“书评”应用程序的母版页已更新,为经过身份验证的用户和匿名用户包含不同的用户界面。 如果匿名用户访问网站,她会在右上角看到“登录”链接。 经过身份验证的用户会看到消息“欢迎返回, 用户名!”以及用于注销的链接。还有一个登录页 (~/Login.aspx) ,其中包含一个登录 Web 控件,该控件提供用于对访问者进行身份验证的用户界面和逻辑。 只有管理员才能创建新帐户。 (文件夹中有用于创建和管理用户帐户 ~/Admin 的页面。)

配置成员资格和角色 API

Book Reviews Web 应用程序使用成员资格和角色 API 来支持用户帐户,并将这些用户分组到角色 (即管理员角色) 。 SqlMembershipProvider使用 和 SqlRoleProvider 提供程序类是因为我们想要将帐户和角色信息存储在 SQL Server 数据库中。

注意

本教程不打算在配置 Web 应用程序以支持成员资格和角色 API 时进行详细检查。 有关这些 API 以及配置网站以使用它们所需的步骤,请阅读我的 网站安全教程

若要将应用程序服务与SQL Server数据库一起使用,必须先将这些提供程序使用的数据库对象添加到要在其中存储用户帐户和角色信息的数据库。 这些必需的数据库对象包括各种表、视图和存储过程。 除非另有指定,SqlMembershipProvider否则 和 SqlRoleProvider 提供程序类使用位于应用程序 App_Data 文件夹中名为 ASPNETDB 的 SQL Server Express Edition 数据库;如果此类数据库不存在,则这些提供程序在运行时使用必要的数据库对象自动创建该数据库。

在存储网站应用程序特定数据的同一数据库中创建应用程序服务数据库对象是可能的,而且通常是理想的做法。 .NET Framework附带了一个名为 aspnet_regsql.exe 的工具,用于在指定的数据库上安装数据库对象。 我已继续使用此工具将这些对象添加到 Reviews.mdf 开发数据库 App_Data) (文件夹中的数据库中。 在本教程稍后将这些对象添加到生产数据库时,我们将了解如何使用此工具。

如果将应用程序服务数据库对象添加到数据库以外的 ASPNETDB 数据库,则需要自定义 SqlMembershipProviderSqlRoleProvider 提供程序类配置,以便它们使用适当的数据库。 若要自定义 Membership 提供程序,请在 中的 Web.config部分中添加成员<资格>元素<system.web>;请使用 <roleManager> 元素配置 Roles 提供程序。 以下代码片段取自 Book Reviews 应用程序的 Web.config ,其中显示了成员资格和角色 API 的配置设置。 请注意,这两者都注册了分别使用 SqlMembershipProviderReviewRole 提供程序的新提供程序ReviewMembershipSqlRoleProvider

<configuration>
    <system.web>
        ...

        <membership defaultProvider="ReviewMembership">
            <providers>
                <clear />

                <add type="System.Web.Security.SqlMembershipProvider" 
                     name="ReviewMembership" 
                     connectionStringName="ReviewsConnectionString" 
                     applicationName="BookReviews" />
            </providers>
        </membership>

        <roleManager enabled="true" defaultProvider="ReviewRole">
            <providers>
                <clear />

                <add type="System.Web.Security.SqlRoleProvider" 
                     name="ReviewRole" 
                     connectionStringName="ReviewsConnectionString" 
                     applicationName="BookReviews" />
            </providers>
        </roleManager>

        ...
    </system.web>
</configuration>

文件 Web.config 元素 <authentication> 也已配置为支持基于表单的身份验证。

<configuration>
    <system.web>
        ...

        <authentication mode="Forms" />

        ...
    </system.web>
</configuration>

限制对管理页面的访问

ASP.NET 使用户或角色通过其 URL 授权 功能轻松授予或拒绝对特定文件或文件夹的访问权限。 (我们在 IIS 与 ASP.NET Development Server 的核心差异教程中简要讨论了 URL 授权,并介绍了 IIS 和 ASP.NET Development Server 如何以不同的方式对静态内容和动态内容应用 URL 授权规则。) 由于我们希望禁止访问~/Admin文件夹,但管理员角色中的用户除外,因此我们需要向此文件夹添加 URL 授权规则。 具体而言,URL 授权规则需要允许具有管理员角色的用户并拒绝所有其他用户。 这是通过将 Web.config 包含以下内容的 文件添加到 ~/Admin 文件夹来实现的:

<?xml version="1.0"?>
<configuration>
    <system.web>
        <authorization>
            <allow roles="Admin" />
            <deny users="*" />
        </authorization>
    </system.web>
</configuration>

有关 ASP.NET URL 授权功能以及如何使用它来阐明用户和角色的授权规则的详细信息,请务必阅读我的网站安全教程中的基于用户的授权基于角色的授权教程。

部署使用应用程序服务的 Web 应用程序

部署使用应用程序服务的网站和将应用程序服务信息存储在数据库中的提供程序时,必须在生产数据库上创建应用程序服务所需的数据库对象。 最初生产数据库不包含这些对象,因此,当应用程序首次部署 (或在添加应用程序服务) 后首次部署时,必须采取额外的步骤在生产数据库上获取这些必需的数据库对象。

如果要将开发环境中创建的用户帐户复制到生产环境,则部署使用应用程序服务的网站时,可能会出现另一个难题。 根据成员身份和角色配置,即使成功将开发环境中创建的用户帐户复制到生产数据库,这些用户也无法登录到生产环境中的 Web 应用程序。 我们将探讨此问题的原因,并讨论如何防止此问题发生。

ASP.NET 附带了一个很好的 网站管理工具 (WSAT) ,可以从 Visual Studio 启动,并允许通过基于 Web 的界面管理用户帐户、角色和授权规则。 遗憾的是,WSAT 仅适用于本地网站,这意味着它不能用于在生产环境中远程管理 Web 应用程序的用户帐户、角色和授权规则。 我们将介绍从生产网站实现类似 WSAT 的行为的不同方法。

使用 aspnet_regsql.exe 添加数据库对象

部署数据库教程介绍了如何将表和数据从开发数据库复制到生产数据库,这些技术当然可用于将应用程序服务数据库对象复制到生产数据库。 另一个选项是 aspnet_regsql.exe 工具,该工具在数据库中添加或删除应用程序服务数据库对象。

注意

该工具 aspnet_regsql.exe 在指定的数据库上创建数据库对象。 它不会将这些数据库对象中的数据从开发数据库迁移到生产数据库。 如果打算将开发数据库中的用户帐户和角色信息复制到生产数据库,请使用 部署数据库 教程中介绍的技术。

让我们看看如何使用 工具将数据库对象添加到生产数据库 aspnet_regsql.exe 。 首先打开 Windows 资源管理器并导航到计算机上的 .NET Framework 版本 2.0 目录 %WINDIR%\ Microsoft.NET\Framework\v2.0.50727。 应在此处找到 aspnet_regsql.exe 该工具。 此工具可以从命令行使用,但它还包括图形用户界面;双击 aspnet_regsql.exe 文件以启动其图形组件。

该工具首先显示解释其用途的初始屏幕。 单击“下一步”转到“选择安装选项”屏幕,如图 1 所示。 在此处,可以选择添加应用程序服务数据库对象或从数据库中删除它们。 由于我们要将这些对象添加到生产数据库,因此请选择“为应用程序服务配置SQL Server”选项,然后单击“下一步”。

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

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

在“选择服务器和数据库”屏幕中,提示输入要连接到数据库的信息。 输入 Web 托管公司提供的数据库服务器、安全凭据和数据库名称,然后单击“下一步”。

注意

输入数据库服务器和凭据后,展开数据库下拉列表时可能会收到错误。 该工具 aspnet_regsql.exe 查询 sysdatabases 系统表以检索服务器上的数据库列表,但某些 Web 托管公司会锁定其数据库服务器,使此信息不公开。 如果收到此错误,可以直接在下拉列表中键入数据库名称。

为工具提供数据库连接信息

图 2:为工具提供数据库连接信息 (单击以查看全尺寸图像)

后续屏幕汇总了即将发生的操作,即应用程序服务数据库对象将添加到指定数据库。 单击“下一步”完成此操作。 片刻后,将显示最后一个屏幕,指出数据库对象已添加, (请参阅图 3) 。

成功!应用程序服务数据库对象已添加到生产数据库

图 3:成功! 应用程序服务数据库对象已添加到生产数据库 (单击以查看全尺寸图像)

若要验证应用程序服务数据库对象是否已成功添加到生产数据库,请打开SQL Server Management Studio并连接到生产数据库。 如图 4 所示,现在应在数据库、 aspnet_Applicationsaspnet_Membershipaspnet_Users等数据库中看到应用程序服务数据库表。

确认数据库对象已添加到生产数据库

图 4:确认数据库对象已添加到生产数据库 (单击 以查看全尺寸图像)

只需在首次部署 Web 应用程序时或在开始使用应用程序服务后首次部署 Web 应用程序时,才需要使用 aspnet_regsql.exe 该工具。 这些数据库对象位于生产数据库上后,无需重新添加或修改它们。

将用户帐户从开发复制到生产

使用 SqlMembershipProviderSqlRoleProvider 提供程序类将应用程序服务信息存储在SQL Server数据库中时,用户帐户和角色信息存储在各种数据库表中,包括 aspnet_Usersaspnet_Membershipaspnet_Rolesaspnet_UsersInRoles等。 如果在开发过程中在开发环境中创建用户帐户,则可以通过从适用的数据库表复制相应的记录,在生产环境中复制这些用户帐户。 如果使用数据库发布向导部署应用程序服务数据库对象,则可能还选择了复制记录,这将导致在开发中创建的用户帐户也处于生产状态。 但是,根据配置设置,你可能会发现在开发中创建帐户并复制到生产环境的用户无法从生产网站登录。 这是怎么回事呢?

SqlMembershipProviderSqlRoleProvider 提供程序类的设计使单个数据库可以充当多个应用程序的用户存储,理论上每个应用程序都可以具有具有相同名称的重叠用户名和角色的用户。 为了获得这种灵活性,数据库在 aspnet_Applications 表中维护应用程序列表,并且每个用户都与其中一个应用程序相关联。 具体而言, aspnet_Users 表中有一个 ApplicationId 列,该列将每个用户绑定到表中的 aspnet_Applications 记录。

除了 列 ApplicationId 之外, aspnet_Applications 该表还包含一个 ApplicationName 列,该列为应用程序提供更易用的名称。 当网站尝试使用用户帐户(例如从登录页验证用户凭据)时,它必须告诉 SqlMembershipProvider 类要使用的应用程序。 它通常通过提供应用程序名称来执行此操作,并且此值来自 中的 Web.config 提供程序配置 - 特别是通过 applicationName 属性。

但是,如果未 applicationName 在 中 Web.config指定属性,会发生什么情况? 在这种情况下,成员身份系统使用应用程序根路径作为 applicationName 值。 applicationName如果未在 中Web.config显式设置 属性,则开发环境和生产环境可能会使用不同的应用程序根目录,因此会与应用程序服务中的不同应用程序名称相关联。 如果发生这种不匹配,则在开发环境中创建的这些用户将具有与ApplicationIdApplicationId生产环境的值不匹配的值。 最终结果是这些用户将无法登录。

注意

如果发现自己处于这种情况中(用户帐户复制到生产环境且值不匹配 ApplicationId )可以编写查询,以将这些不正确的 ApplicationId 值更新为 ApplicationId 生产中使用的 。 更新后,在开发环境中创建了帐户的用户现在可以在生产环境中登录到 Web 应用程序。

好消息是,可以采取一个简单的步骤来确保两个环境使用相同的 ApplicationId - 为所有应用程序服务提供程序显式在 中Web.config设置 applicationName 属性。 我在 和 <roleManager> 元素中<membership>显式将 属性设置为applicationName“BookReviews”,如此代码片段Web.config所示。

<membership defaultProvider="ReviewMembership">
    <providers>
        <clear />

        <add type="System.Web.Security.SqlMembershipProvider" 
             name="ReviewMembership" 
             connectionStringName="ReviewsConnectionString" 
             applicationName="BookReviews" />
    </providers>
</membership>

有关设置 applicationName 属性及其背后的基本原理的更多讨论,请参阅 Scott Guthrie 的博客文章: 配置 ASP.NET Membership 和其他提供程序时始终设置 applicationName 属性

在生产环境中管理用户帐户

ASP.NET 网站管理工具 (WSAT) 使创建和管理用户帐户、定义和应用角色以及拼写基于用户和角色的授权规则变得简单。 可以从 Visual Studio 启动 WSAT,方法是转到解决方案资源管理器并单击“ASP.NET 配置”图标,或者转到“网站或项目”菜单并选择“ASP.NET 配置”菜单项。 遗憾的是,WSAT 只能与本地网站一起使用。 因此,不能使用工作站中的 WSAT 来管理生产环境中的网站。

好消息是,WSAT 提供的所有功能都可以通过成员资格和角色 API 以编程方式使用;此外,许多 WSAT 屏幕使用与登录相关的标准 ASP.NET 控件。 简言之,你可以向网站添加 ASP.NET 页面,以提供必要的管理功能。

回想一下,前面的教程更新了书评 Web 应用程序以包含一个~/Admin文件夹,并且此文件夹已配置为仅允许管理员角色中的用户。 我向该文件夹添加了一个名为 CreateAccount.aspx 的页面,管理员可以从该文件夹中创建新的用户帐户。 此页使用 CreateUserWizard 控件显示用于创建新用户帐户的用户界面和后端逻辑。 此外,我自定义了控件以包含一个 CheckBox,提示是否还应将新用户添加到管理员角色 (请参阅图 5) 。 通过一点点工作,可以生成一组自定义页面,用于实现与用户和角色管理相关的任务,否则 WSAT 将提供这些任务。

注意

有关使用成员身份和角色 API 以及与登录相关的 ASP.NET Web 控件的详细信息,请务必阅读我的 网站安全教程。 有关自定义 CreateUserWizard 控件的详细信息,请参阅创建用户帐户存储其他用户信息教程,或检查 Erich Peterson 文章自定义 CreateUserWizard 控件

管理员可以创建新的用户帐户

图 5:管理员可以创建新的用户帐户 (单击以查看全尺寸映像)

如果需要 WSAT 的完整功能,检查推出“推出自己的网站管理工具”,其中作者 Dan Clem 将演练生成类似 WSAT 的自定义工具的过程。 Dan 在 C#) 中共享其应用程序的源代码 (,并提供将其添加到托管网站的分步说明。

摘要

部署使用应用程序服务数据库实现的 Web 应用程序时,必须先确保生产数据库具有必需的数据库对象。 可以使用 部署数据库 教程中所述的技术添加这些对象;或者,可以使用 aspnet_regsql.exe 该工具,如本教程所示。 围绕同步开发和生产环境中使用的应用程序名称 (我们涉及的其他挑战,如果希望在开发环境中创建的用户和角色在生产环境中) 以及管理生产环境中的用户和角色的技术上有效,这一点非常重要。

编程快乐!

深入阅读

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