安全基础知识和 ASP.NET 支持 (C#)
作者 :斯科特·米切尔
注意
自本文撰写以来,ASP.NET 成员身份提供程序已被 ASP.NET 标识取代。 强烈建议更新应用以使用 ASP.NET 标识 平台,而不是本文撰写时精选的成员资格提供程序。 ASP.NET 标识在 ASP.NET 成员身份系统中具有许多优势,包括:
- 性能更好
- 改进了可扩展性和可测试性
- 支持 OAuth、OpenID Connect 和双因素身份验证
- 基于声明的标识支持
- 与 ASP.Net Core 更好的互操作性
这是一系列教程中的第一个教程,将探索通过 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 帐户。
通过窗体身份验证进行身份验证
另一方面,表单身份验证非常适合 Internet Web 应用程序。 回想一下,表单身份验证通过提示用户通过 Web 表单输入其凭据来标识用户。 因此,当用户尝试访问未经授权的资源时,他们会自动重定向到登录页,可在其中输入其凭据。 然后,根据自定义用户存储(通常是数据库)验证提交的凭据。
验证提交的凭据后, 将为用户创建表单身份验证票证 。 此票证指示用户已经过身份验证,并包括标识信息,例如用户名。 表单身份验证票证(通常)作为 Cookie 存储在客户端计算机上。 因此,后续访问网站包括 HTTP 请求中的表单身份验证票证,从而使 Web 应用程序能够在用户登录后识别用户。
图 2 演示了来自高级优势的表单身份验证工作流。 请注意 ASP.NET 中的身份验证和授权部分如何充当两个单独的实体。 表单身份验证系统标识用户(或报告他们是匿名的)。 授权系统确定用户是否有权访问请求的资源。 如果用户未授权(如图 2 中尝试匿名访问ProtectedPage.aspx),授权系统将报告用户被拒绝,导致表单身份验证系统自动将用户重定向到登录页。
用户成功登录后,后续 HTTP 请求将包括表单身份验证票证。 表单身份验证系统仅标识用户 - 它是确定用户是否可以访问所请求资源的授权系统。
图 2:表单身份验证工作流
我们将在下一教程“表单身份验证概述”中更详细地了解表单身份验证。 有关 ASP 的详细信息。NET 的身份验证选项,请参阅 ASP.NET 身份验证。
限制对网页、目录和页面功能的访问
ASP.NET 包括两种方法来确定特定用户是否有权访问特定文件或目录:
- 文件授权 - 由于 ASP.NET 页和 Web 服务作为驻留在 Web 服务器的文件系统上的文件实现,因此可以通过访问控制列表(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 中提供两个成员资格提供程序类:
- ActiveDirectoryMembershipProvider - 在 Active Directory 和 Active Directory 应用程序模式 (ADAM) 服务器中实现成员身份 API。
- SqlMembershipProvider - 在 SQL Server 数据库中实现成员身份 API。
本教程系列专门介绍 SqlMembershipProvider。
图 03:提供程序模型允许将不同的实现无缝插入框架(单击以查看全尺寸图像)
提供程序模型的好处是,Microsoft、第三方供应商或单个开发人员可以开发替代实现,并无缝地插入成员资格框架。 例如,Microsoft已为 Microsoft Access 数据库发布了成员资格提供程序。 有关成员资格提供程序的详细信息,请参阅 提供程序工具包,其中包括成员资格提供程序演练、示例自定义提供程序、提供程序模型上超过 100 页的文档,以及内置成员身份提供程序的完整源代码(即 ActiveDirectoryMembershipProvider 和 SqlMembershipProvider)。
ASP.NET 2.0 还引入了角色框架。 与成员资格框架一样,角色框架是在提供程序模型之上构建的。 其 API 通过 Roles 类 公开,.NET Framework 附带三个提供程序类:
- AuthorizationStoreRoleProvider - 管理授权管理器策略存储中的角色信息,例如 Active Directory 或 ADAM。
- SqlRoleProvider - 在 SQL Server 数据库中实现角色。
- WindowsTokenRoleProvider - 基于访问者的 Windows 组关联角色信息。 此方法通常用于Windows 身份验证。
本教程系列专门介绍 SqlRoleProvider。
由于提供程序模型包含单个面向前向的 API(成员资格和角色类),因此可以在该 API 周围构建功能,而无需担心实现详细信息 - 这些由页面开发人员选择的提供程序处理。 此统一 API 允许Microsoft和第三方供应商生成与成员资格和角色框架进行交互的 Web 控件。 ASP.NET 附带许多用于实现常见用户帐户用户界面的 登录 Web 控件 。 例如, 登录控件 会提示用户输入其凭据、验证凭据,然后通过表单身份验证将其登录。 LoginView 控件提供用于向匿名用户显示不同标记的模板,以及基于用户角色的不同标记。 CreateUserWizard 控件提供了用于创建新用户帐户的分步用户界面。
下面介绍了各种登录控件与成员资格和角色框架交互。 大多数登录控件都可以实现,而无需编写单行代码。 我们将在未来的教程中更详细地检查这些控件,包括扩展和自定义其功能的技术。
总结
支持用户帐户的所有 Web 应用程序都需要类似的功能,例如:用户能够登录并在页面访问期间记住其登录状态;新访问者用于创建帐户的网页;页面开发人员能够指定哪些资源、数据和功能可供哪些用户或角色使用。 由于表单身份验证、URL 授权和成员资格和角色框架,在 ASP.NET 应用程序中对用户进行身份验证和授权以及管理用户帐户和角色的任务非常容易。
在接下来的几个教程中,我们将逐步从头构建工作 Web 应用程序来研究这些方面。 在下两个教程中,我们将详细介绍表单身份验证。 我们将看到表单身份验证工作流正在运行,剖析表单身份验证票证,讨论安全问题,以及如何配置表单身份验证系统 - 同时构建允许访问者登录和注销的 Web 应用程序。
快乐编程!
深入阅读
有关本教程中讨论的主题的详细信息,请参阅以下资源:
- ASP.NET 2.0 成员身份、角色、表单身份验证和安全资源
- ASP.NET 2.0 安全准则
- ASP.NET 身份验证
- ASP.NET 授权
- ASP.NET 登录控件概述
- 检查 ASP.NET 2.0 的成员身份、角色和配置文件
- 如何:使用成员身份和角色保护我的站点? (视频)
- 成员资格简介
- MSDN 安全开发人员中心
- 专业 ASP.NET 2.0 安全、成员资格和角色管理 (ISBN:978-0-7645-9698-8)
- 提供程序工具包
关于作者
斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0。 他可以通过他的博客联系到mitchell@4GuysFromRolla.com他,可以在该博客中找到http://ScottOnWriting.NET。
特别感谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者包括 Alicja Maziarz、John Suru 和 Teresa Murphy。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请把我扔一条线。mitchell@4GuysFromRolla.com