安全基础知识和 ASP.NET 支持 (VB)

作者 :Scott Mitchell

注意

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

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

下载 PDF

这是一系列教程中的第一个教程,这些教程将探讨如何通过 Web 表单对访问者进行身份验证、授权访问特定页面和功能以及管理 ASP.NET 应用程序中的用户帐户。

简介

论坛、电子商务网站、在线电子邮件网站、门户网站和社交网络网站有哪些共同点? 它们都提供 用户帐户。 提供用户帐户的站点必须提供大量服务。 新访问者至少需要能够创建一个帐户,并且返回的访问者必须能够登录。 此类 Web 应用程序可以根据登录的用户做出决策:某些页面或操作可能限制为仅登录用户或特定子集用户;其他页面可能会显示特定于已登录用户的信息,也可能显示更多或更少的信息,具体取决于正在查看页面的用户。

这是一系列教程中的第一个教程,这些教程将探讨如何通过 Web 表单对访问者进行身份验证、授权访问特定页面和功能以及管理 ASP.NET 应用程序中的用户帐户。 在这些教程中,我们将了解如何:

  • 识别用户并将其登录到网站
  • 使用 ASP。用于管理用户帐户的 NET 成员资格框架
  • 创建、更新和删除用户帐户
  • 根据登录的用户限制对网页、目录或特定功能的访问
  • 使用 ASP。NET 的角色框架,用于将用户帐户与角色相关联
  • 管理用户角色
  • 根据登录用户的角色限制对网页、目录或特定功能的访问
  • 自定义和扩展 ASP。NET 的安全 Web 控件

这些教程旨在简洁,并提供分步说明和大量屏幕截图,以直观地引导你完成该过程。 每个教程都以 C# 和 Visual Basic 版本提供,并包括所用完整代码的下载。 (第一个教程重点介绍从高级角度讲安全概念,因此不包含任何关联的代码。)

在本教程中,我们将讨论重要的安全概念,以及 ASP.NET 中提供哪些工具来帮助实现表单身份验证、授权、用户帐户和角色。 现在就开始吧!

注意

安全性是任何应用程序的重要方面,它涉及物理、技术和策略决策,需要高度的规划和领域知识。 本教程系列不用作开发安全 Web 应用程序的指南。 相反,它特别侧重于表单身份验证、授权、用户帐户和角色。 虽然本系列中讨论了围绕这些问题的一些安全概念,但其他概念尚未探索。

身份验证、授权、用户帐户和角色

身份验证、授权、用户帐户和角色是本系列教程中经常使用的四个术语,因此我想花点时间在 Web 安全上下文中定义这些术语。 在客户端-服务器模型(如 Internet)中,在很多情况下,服务器需要标识发出请求的客户端。 身份验证 是确定客户端标识的过程。 已成功识别的客户据说已经过 身份验证。 身份不明的客户端据说 未经身份验证匿名

安全身份验证系统至少涉及以下三个方面之一: 你知道的东西、你拥有的东西,或者你拥有的东西。 大多数 Web 应用程序依赖于客户端知道的内容,例如密码或 PIN。 用于标识用户的信息(例如用户的用户名和密码)称为 凭据。 本教程系列重点介绍 表单身份验证,这是一种身份验证模型,用户可通过在网页表单中提供凭据登录到站点。 我们以前都经历过此类身份验证。 转到任何电子商务网站。 当你准备好检查要求你登录,方法是在网页上的文本框中输入用户名和密码。

除了标识客户端之外,服务器可能需要根据发出请求的客户端限制可访问的资源或功能。 授权 是确定特定用户是否有权访问特定资源或功能的过程。

用户帐户是一个存储区,用于保存有关特定用户的信息。 用户帐户必须至少包含唯一标识用户的信息,例如用户的登录名和密码。 除了这些基本信息,用户帐户可能包括以下内容:用户的电子邮件地址;创建帐户的日期和时间;上次登录的日期和时间;名字和姓氏;电话号码;和邮寄地址。 使用表单身份验证时,用户帐户信息通常存储在 Microsoft SQL Server 等关系数据库中。

支持用户帐户的 Web 应用程序可以选择将用户分组为 角色。 角色只是应用于用户的标签,提供用于定义授权规则和页面级功能的抽象。 例如,网站可能包含具有授权规则的管理员角色,这些规则禁止除管理员外任何人访问一组特定的网页。 此外,所有用户都可以访问的各种页面, (包括非管理员) ,当作为管理员角色的用户访问时,可能会显示其他数据或提供额外的功能。 使用角色,我们可以逐个角色而不是逐个用户定义这些授权规则。

在 ASP.NET 应用程序中对用户进行身份验证

当用户在其浏览器的地址窗口中输入 URL 或单击链接时,浏览器会向 Web 服务器发出 超文本传输协议 (HTTP) 请求以获取指定内容,无论是 ASP.NET 页面、图像、JavaScript 文件还是任何其他类型的内容。 Web 服务器的任务是返回请求的内容。 在执行此操作时,它必须确定有关请求的一些事项,包括发出请求的人员以及标识是否有权检索请求的内容。

默认情况下,浏览器发送缺少任何类型的标识信息的 HTTP 请求。 但是,如果浏览器确实包含身份验证信息,则 Web 服务器将启动身份验证工作流,该工作流将尝试识别发出请求的客户端。 身份验证工作流的步骤取决于 Web 应用程序使用的身份验证类型。 ASP.NET 支持三种类型的身份验证:Windows、Passport 和窗体。 本教程系列重点介绍表单身份验证,但让我们花一点时间Windows 身份验证用户存储和工作流进行比较和对比。

通过 Windows 身份验证进行身份验证

Windows 身份验证工作流使用以下身份验证技术之一:

  • 基本身份验证
  • 摘要式身份验证
  • Windows 集成身份验证

这三种方法的工作方式大致相同:当未经授权的匿名请求到达时,Web 服务器会发回一个 HTTP 响应,指示需要授权才能继续。 然后,浏览器将显示一个模式对话框,提示用户输入其用户名和密码 (见图 1) 。 然后,此信息通过 HTTP 标头发送回 Web 服务器。

模式对话框提示用户输入其凭据

图 1:模式对话框提示用户输入其凭据

提供的凭据将针对 Web 服务器的 Windows 用户应用商店进行验证。 这意味着,Web 应用程序中每个经过身份验证的用户必须在组织中具有 Windows 帐户。 这在 Intranet 方案中很常见。 事实上,在 Intranet 设置中使用 Windows 集成身份验证时,浏览器会自动向 Web 服务器提供用于登录到网络的凭据,从而禁止显示图 1 所示的对话框。 虽然Windows 身份验证非常适合 Intranet 应用程序,但它通常不适用于 Internet 应用程序,因为你不希望为在站点注册的每个用户创建 Windows 帐户。

通过 Forms 身份验证进行身份验证

另一方面,表单身份验证非常适合 Internet Web 应用程序。 回想一下,表单身份验证通过提示用户通过 Web 表单输入其凭据来标识用户。 因此,当用户尝试访问未经授权的资源时,他们会自动重定向到登录页,他们可以在其中输入其凭据。 然后,针对自定义用户存储(通常是数据库)验证提交的凭据。

验证提交的凭据后,会为用户创建 表单身份验证票证 。 此票证指示用户已经过身份验证,并包含标识信息,例如用户名。 表单身份验证票证通常 () 存储为客户端计算机上的 Cookie。 因此,后续访问网站包括 HTTP 请求中的表单身份验证票证,从而使 Web 应用程序能够在用户登录后识别用户。

图 2 从高级角度说明了表单身份验证工作流。 请注意,ASP.NET 中的身份验证和授权部分如何充当两个单独的实体。 表单身份验证系统标识用户 (或报告是匿名) 。 授权系统确定用户是否有权访问请求的资源。 如果用户在尝试匿名访问ProtectedPage.aspx) 时未授权 (,则授权系统会报告该用户被拒绝,从而导致表单身份验证系统自动将用户重定向到登录页。

用户成功登录后,后续 HTTP 请求将包括表单身份验证票证。 表单身份验证系统仅标识用户 - 授权系统确定用户是否可以访问请求的资源。

表单身份验证工作流

图 2:表单身份验证工作流

我们将在下一教程表单身份验证概述中更详细地探讨表单身份验证。 有关 ASP 的详细信息。NET 的身份验证选项,请参阅 ASP.NET 身份验证

限制对网页、目录和页面功能的访问

ASP.NET 包括两种方法来确定特定用户是否有权访问特定文件或目录:

  • 文件授权 - 由于 ASP.NET 页和 Web 服务实现为驻留在 Web 服务器的文件系统上的文件,因此可以通过访问控制 Lists (ACL) 指定对这些文件的访问。 文件授权最常用于 Windows 身份验证因为 ACL 是适用于 Windows 帐户的权限。 使用表单身份验证时,所有操作系统和文件系统级请求都由同一 Windows 帐户执行,而不考虑访问站点的用户。
  • URL 授权 - 使用 URL 授权,页面开发人员在 Web.config 中指定授权规则。这些授权规则指定允许哪些用户或角色访问或拒绝访问应用程序中的某些页面或目录。

文件授权和 URL 授权定义访问特定 ASP.NET 页面或特定目录中所有 ASP.NET 页的授权规则。 使用这些技术,我们可以指示 ASP.NET 拒绝对特定用户的特定页面的请求,或者允许访问一组用户并拒绝其他人的访问权限。 那么,所有用户都可以访问页面,但页面功能取决于用户的情况呢? 例如,许多支持用户帐户的网站的页面显示经过身份验证的用户与匿名用户的不同内容或数据。 匿名用户可能会看到用于登录站点的链接,而经过身份验证的用户将看到类似“欢迎回来”、“ 用户名” 等消息以及用于注销的链接。另一个示例:在拍卖网站上查看商品时,将看到不同的信息,具体取决于您是竞拍者还是拍卖该项目的人。

此类页面级调整可以通过声明方式或编程方式完成。 若要显示与经过身份验证的用户不同的匿名内容,只需将 LoginView 控件 拖到页面上,并将相应内容输入到其 AnonymousTemplate 和 LoggedInTemplate 模板中。 或者,你可以以编程方式确定当前请求是否经过身份验证、用户是谁,以及他们属于哪些角色 (是否有任何) 。 然后,可以使用此信息在页面上的网格或面板中显示或隐藏列。

本系列包括三个侧重于授权的教程。 基于用户的授权检查如何限制对目录中页面或特定用户帐户的页面的访问; 基于角色的授权 考虑在角色级别提供授权规则;最后, 基于当前登录用户的显示内容 教程探索了基于访问该页面的用户修改特定页面的内容和功能。 有关 ASP 的详细信息。NET 的授权选项,请参阅 ASP.NET 授权

用户帐户和角色

Asp。NET 的表单身份验证为用户提供了一个基础结构,使用户能够登录到站点,并在页面访问中记住其身份验证状态。 URL 授权提供了一个框架,用于限制对 ASP.NET 应用程序中特定文件或文件夹的访问。 但是,这两项功能都无法存储用户帐户信息或管理角色。

在 ASP.NET 2.0 之前,开发人员负责创建自己的用户和角色存储。 他们还负责设计用户界面和编写基本用户帐户相关页面(如登录页)的代码,以及创建新帐户的页面等。 ASP.NET 中没有任何内置用户帐户框架,每个实现用户帐户的开发人员必须就如何实现存储密码或其他敏感信息等问题做出自己的设计决策?关于密码长度和强度,我应实施哪些准则?

如今,由于 成员资格框架 和内置的登录 Web 控件,在 ASP.NET 应用程序中实现用户帐户要简单得多。 成员资格框架是 System.Web.Security 命名空间 中的少数类,提供执行与用户帐户相关的基本任务的功能。 Membership 框架中的关键类是 Membership 类,其方法如下:

  • CreateUser
  • DeleteUser
  • GetAllUsers
  • GetUser
  • UpdateUser
  • ValidateUser

成员资格框架使用 提供程序模型,该模型将成员资格框架的 API 与其实现完全分离。 这使开发人员能够使用通用 API,但使他们能够使用满足其应用程序的自定义需求的实现。 简言之,Membership 类定义框架的基本功能, (方法、属性和事件) ,但实际上不提供任何实现详细信息。 相反,Membership 类的方法调用配置的提供程序,这是执行实际工作的提供程序。 例如,调用 Membership 类的 CreateUser 方法时,Membership 类不知道用户存储的详细信息。 它不知道用户是在数据库、XML 文件中还是在某个其他存储中维护。 Membership 类检查 Web 应用程序的配置以确定要委托调用的提供程序,并且该提供程序类负责在相应的用户存储区中实际创建新用户帐户。 图 3 演示了这种交互。

Microsoft 在.NET Framework中提供了两个成员资格提供程序类:

本教程系列专门介绍 SqlMembershipProvider。

提供程序模型允许将不同的实现无缝插入到框架中

图 03:提供程序模型允许将不同的实现无缝插入框架 (单击以查看全尺寸图像)

提供程序模型的优点是,替代实现可由 Microsoft、第三方供应商或单个开发人员开发,并无缝插入成员资格框架。 例如,Microsoft 发布了 Microsoft Access 数据库的成员资格提供程序。 有关成员资格提供程序的详细信息,请参阅 提供程序工具包,其中包括成员资格提供程序、示例自定义提供程序的演练、有关提供程序模型的超过 100 页的文档,以及内置成员身份提供程序的完整源代码 (ActiveDirectoryMembershipProvider 和 SqlMembershipProvider) 。

ASP.NET 2.0 还引入了角色框架。 与成员资格框架一样,角色框架是在提供程序模型之上构建的。 其 API 通过 Roles 类公开,.NET Framework附带三个提供程序类:

本教程系列专门介绍 SqlRoleProvider。

由于提供程序模型包含单个面向的 API (成员资格类和角色类) ,因此可以围绕该 API 生成功能,而无需担心实现详细信息 - 这些由页面开发人员选择的提供程序处理。 此统一 API 允许 Microsoft 和第三方供应商生成与成员资格和角色框架交互的 Web 控件。 ASP.NET 附带了许多用于实现常见用户帐户用户界面的 登录 Web 控件 。 例如, Login 控件 会提示用户输入其凭据,对其进行验证,然后通过表单身份验证将其登录。 LoginView 控件提供模板,用于向匿名用户和经过身份验证的用户显示不同的标记,或者根据用户的角色显示不同的标记。 CreateUserWizard 控件提供用于创建新用户帐户的分步用户界面。

下面介绍了各种 Login 控件与成员资格和角色框架交互。 大多数 Login 控件无需编写一行代码即可实现。 我们将在将来的教程中更详细地研究这些控件,包括扩展和自定义其功能的技术。

总结

支持用户帐户的所有 Web 应用程序都需要类似的功能,例如:用户能够登录并在页面访问中记住其登录状态;供新访问者创建帐户的网页;以及页面开发人员指定哪些资源、数据和功能可用于哪些用户或角色的功能。 由于表单身份验证、URL 授权以及成员身份和角色框架,在 ASP.NET 应用程序中,对用户进行身份验证和授权以及管理用户帐户和角色的任务非常简单。

在接下来的几个教程中,我们将通过分步从头开始构建一个正常运行的 Web 应用程序来研究这些方面。 在接下来的两个教程中,我们将详细介绍表单身份验证。 我们将了解表单身份验证工作流的运行情况,剖析表单身份验证票证,讨论安全问题,并了解如何配置表单身份验证系统 - 同时构建允许访问者登录和注销的 Web 应用程序。

编程快乐!

深入阅读

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

关于作者

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

特别感谢

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