导出 (0) 打印
全部展开

使用 Azure AD 为 Web 应用程序添加登录

更新时间: 2014年5月

note备注
此示例已过时,其技术、方法和/或用户界面说明已由较新的功能替换。若要查看生成类似应用程序的已更新示例,请参阅 WebApp-OpenIDConnect-DotNet

.

此演练将显示如何使用 Azure AD 在 ASP.NET 应用程序中实现 Web 单一登录。说明将重点介绍如何利用与 Azure 订阅关联的目录租户,因为后者实质上就是选择组织中业务线 (LoB) 应用程序的标识提供者。

Web 单一登录解决方案通常需要将 Web 应用程序配置为将其身份验证功能外包给某个通常称为标识提供者 (IdP) 的外部实体。具体而言,这意味着将应用程序配置为根据某些登录协议(如 SAML-P、WS-Federation 或 OpenID Connect)将未经身份验证的请求重定向到 IdP。

权威机构(或 IdP)将处理身份验证体验,并且通常会要求已通过某些设置过程了解了 Web 应用程序。身份验证成功后,会将浏览器与携带传入用户相关信息的安全令牌一起重定向回 Web 应用;应用程序通常将通过一些可识别标识的中间件验证该令牌,而如果检查成功,则认可用户通过身份验证并让其登录。

该概要说明也适用于 Azure AD。本文档将显示如何使用 Visual Studio 2012 和 .NET Framework 4.5 中的 Windows Identity Foundation (WIF) 类将 MVC 4 应用程序配置为使用 Web 登录协议。它将显示如何在 Azure AD 租户中设置同一应用程序,以及如何将应用程序的登录设置配置为连接到该租户。在本演练的最后,你将拥有一个完全为组织单一登录配置的正常运行的 Web 应用程序。

本演练的目的是帮助你了解 Azure AD 的运作方式,因此,除了讲述如何将此处所述的简化解决方案综合在一起,还必须讲述更深入的内容。除了向你提供构建工作示例的具体说明外,本文档还将介绍一些项目和概念,这些项目和概念将有助于你了解 Azure AD,以及了解如何利用其在此处讨论的特定方案以外的功能。这些额外部分(设置为框笔记格式)并不是执行本演练所一定需要的内容;但是,如果你有兴趣在自己的解决方案中使用 Azure AD,建议你也阅读这些部分。

本文档的此教程部分分为以下各节:

  • 先决条件:此节列出了完成本演练必须满足的所有要求。

  • 解决方案体系结构:此节概要介绍 LoB(业务线)应用程序的 Web SSO 解决方案的大致内容。我们将研究促使 SSO 发生的功能组件,并设置线框,稍后你将按照本文档的说明充实该线框。

  • 使用 Azure AD Directory 租户:此节介绍 Azure AD 租户以及将在本方案中发挥作用的功能。它还将简要介绍 Azure 管理门户的 Active Directory 部分的主要元素。

  • 将应用程序连接到 Azure AD:此节显示如何使用用于 Visual Studio 2012 的标识和访问工具在 MVC 应用程序中实现 Web 单一登录,以及如何将身份验证设置关联到所选的特定 Azure AD 租户。

  • 高级主题:此节超出基础知识的范围,深入研究一些关键主题,并涵盖使应用程序更上一个层次可能需要执行的一些其他任务。

完成本教程需要以下先决条件:

如果你有疑问或需要帮助,请参阅Preparing for Azure AD Solutions and Scenarios

单租户应用程序体系结构

本演练主要针对以下应用场景:开发人员要开发一个计划部署在云中的 Web 应用程序,他只想让 Azure Active Directory 租户中的用户访问它。若要实现此功能,他将需要:

  1. 在 Azure AD 租户中注册该 Web 应用。了解该应用后,Azure AD 将接受用户针对其进行身份验证的请求。

  2. 在该应用前面添加内容,以便:

    1. 阻止未经身份验证的请求,并将其重定向到相应的 Azure AD 租户进行用户身份验证

    2. 识别已通过 Azure AD 进行身份验证的用户并向其授予访问权限

我们将使用 Azure 管理门户实现第一步。你将了解如何在 Azure 订阅中设置新的 Azure AD 租户,以及如何运用 Azure AD 管理门户功能注册应用程序。

可以使用多种高级协议实现第 2 步,以便跨组织边界甚至在整个 Internet 上进行身份验证操作。

在 .NET 平台上,可以将第二步归结为配置 .NET 提供的现成类,将其用于基于声明的标识和联合身份验证。这些类统称为 Windows Identity Foundation (WIF),它们包括 HTTP 模块和配置设置,可用于添加拦截层来执行第 2 步中介绍的重定向和身份验证任务。Visual Studio 2012 提供相关工具,可帮助你自动将 Web 应用配置为使用 WIF 将身份验证外包给支持 WS-Federation 等特定 Web SSO 协议的外部权威机构;本演练显示如何将此类工具用于 Azure AD。

Azure Active Directory 是提供 Microsoft 产品(例如 Office 365 和 Windows Intune)的标识主干的服务。如果你订阅了这些服务,并想要重用与该服务关联的目录租户,请创建新的 Azure 订阅并使用“添加用户”功能从该租户添加管理员。本演练将不会提供有关该过程的详细指导。

每个订阅均有 Azure AD 租户和关联的目录。如果自动生成租户,则会将该目录命名为“默认目录”,但你可以更改该名称。在此部分的演练中,我们会将一个用户添加到该目录中,然后添加一个应用程序。

创建目录租户时,该租户将配置为在云中存储用户和凭据。有关如何将目录租户与 Windows Server Active Directory 的本地部署集成的详细说明,请参阅目录集成

如果你有疑问或需要帮助,请参阅Preparing for Azure AD Solutions and Scenarios

Azure AD 应用场景和解决方案(以及我们的代码示例和示例应用程序)需要使用 Azure Active Directory 域中的用户帐户。如果你尝试使用 Microsoft 帐户(如 Hotmail.com、Live.com 或 Outlook.com 帐户)登录到应用程序,则登录将失败。如果你已有一个具有 Active Directory 域中帐户(如 User@Contoso.onmicrosoft.com 帐户)的用户,则可以使用该帐户来登录到此应用场景。否则,你将需要创建一个新用户。

  1. 转到 Microsoft Azure 管理门户 (https://manage.WindowsAzure.com) 并登录,然后单击“Active Directory”。(故障排除提示:“Active Directory”项缺失或不可用

  2. 如果你的目录名为“默认目录”,请添加一个目录,如“ContosoEngineering”。若要添加目录,请在 Active Directory 页底部单击“添加”,然后按照说明添加新目录。

  3. 右键单击该目录,然后单击“域”。创建用户帐户时,请使用该页上显示的域名。例如,如果域为 ContosoEngineering@onmicrosoft.com,请在该域中创建用户名,如 Test@ContosoEngineering@onmicrosoft.com。

  4. 若要在该域中创建用户帐户,请单击“用户”。(如果未看到“用户”选项卡,请双击目录名称。此时“用户”选项卡将显示在每个目录特定的页上。)在页面底部,单击“添加用户”

  5. 选择“在组织中新建用户”。将用户(如 Test@ContosoEngineering.onmicrosoft.com)添加到新域中,然后单击页面底部的复选标记。

    输入用户名和域
  6. “用户配置文件”页上,为用户分配组织角色。为了进行测试,最好至少有一个具有“全局管理员”角色的用户和一个具有“用户”角色的用户。

    输入用户角色

在最后一步中,Azure 管理门户将生成临时密码,供用户首次登录时使用。首次登录完成后,用户必须更改临时密码。请务必保存临时密码,因为我们需要使用它来测试方案。

至此,我们已拥有一个包含一个有效用户的目录租户,该租户在我们的 Web 单一登录方案中提供身份验证机构。

临时密码

  1. 让我们从应用程序部分开始我们的工作。打开 Visual Studio,单击“新建项目”,然后选取“ASP.NET MVC 4 Web 应用程序”。在“新 ASP.NET MVC 4 项目”窗口中,选择“Intranet 应用程序”,确保视图引擎设置为 Razor,然后单击“确定”。在本演练中,我们将使用 ExpenseReport 作为项目名称。

    note备注
    本演练假定 Visual Studio 安装配置了其默认设置。如果你更改了某些基本配置(例如,开发时托管 Web 应用程序的位置),则必须对说明进行相应的调整。



    Visual Studio 中的新项目

    你可以将本演练中的说明应用于任何现有的 VS 2012 Web 应用程序、MVC 或 Web 窗体,前提是你未使用任何极大地变更了 ASP.NET 请求处理管道的逻辑。但是,为简单起见,我们将在此处从头开始构建一个新项目。

    note备注
    本演练提供的是有关如何设置 .NET 解决方案的详细说明,但是其他平台和编程堆栈也能获得相同的结果。Azure AD 在其 Web 登录功能中使用开放协议,而每个主要平台都提供支持这种协议的库和工具。必须调整详细的操作步骤,使之适合每个堆栈的语法和实践,不过可以全面应用概述型任务细分。

    Visual Studio 会为你创建一个新的 MVC 项目,该项目已配置为在 IIS Express 上运行:我们将不会进一步为该项目添加功能,因为默认设置已足够用于演示如何添加 Web 登录。唯一的例外是应用程序使用的终结点。默认情况下,Visual Studio 将应用程序配置为通过 HTTP 提供内容服务,但是,该配置并不适合建立安全会话,因为它会使通信处于未保护状态,并允许潜在攻击者窃取 Cookie 和令牌。在开发阶段这不是必需的,因为 Azure 不会严格强制使用 HTTPS。但是,这始终是一种好的做法。

  2. 使用 IIS Express 可非常轻松地从 Visual Studio 直接启用 HTTPS。在解决方案资源管理器中选择你的项目,然后在“属性”窗格中,将“启用 SSL”切换到 True

    你将看到先前为空的 SSL URL 将使用新地址进行填充。选择它并将它复制到剪贴板上。



    复制 SSL URL

  3. 现在,我们需要让 Visual Studio 知道我们在调试期间始终要使用 HTTPS 终结点。返回到解决方案资源管理器,右键单击该项目,然后选择“属性”。选择左侧的 Web 选项卡,向下滚动到“使用本地 IIS Web 服务器”选项,并将 HTTPS URL 粘贴到“项目 URL”字段中。保存设置 (CTRL+S) 并关闭“属性”选项卡。



    更改项目 URL

    至此,我们已有一个适合配置为利用 Azure AD 进行登录的应用程序。下一步是让 Azure AD 租户了解此特定应用的相关信息。

  1. 使 Visual Studio 最小化,并返回到 Azure 管理门户中的 Active Directory 选项卡。在本演练的前面部分,我们在“用户”区域中操作;现在,我们将在“应用程序”区域中操作。在页面顶部单击“应用程序”



    集成的应用程序

    此区域将列出已在目录租户中注册的应用程序。在以下情况下,我们认为应用程序已在租户中注册

    • 应用程序在目录中有一个条目,该条目描述了应用程序的主要对等项:名称、关联的终结点等。更多详细信息在后面说明。

    • 已向应用程序本身授予对当前目录租户执行某些操作的权限:从请求登录令牌到启用目录查询,都属于操作范围。有关此内容的更多详细信息也在后面说明。

    Important重要提示
    没有应用程序可以在未注册的情况下利用 Azure AD:这既是出于安全原因(只应允许管理员批准的应用),又有实际的考量(与 Azure AD 交互需要使用特定的开放协议,因而需要了解描述此应用的关键参数)。

  2. 鉴于我们刚开始创建此目录租户,已注册应用程序的列表仍然为空。实际上,第一个条目将会用于我们刚在 Visual Studio 中创建的应用程序:此节将仅讲述如何将它注册为应用。

    鉴于这是第一个应用,请通过单击屏幕底部 Azure 管理门户命令栏上的“添加”按钮来开始此过程。然后,你将会看到下面的屏幕提示:



    向我们说明您的应用程序

    通过 Azure 管理门户注册应用的过程以经典向导所示的方式进行。在该向导中,后续屏幕将根据你的选择对所需信息的收集过程进行细分。

    上图显示了这些屏幕中的第一个屏幕。提供的选项很简单:

    • 显示名称:此处输入的文本在用户(无论是管理已注册应用列表的管理员,还是决定授予对应用的目录访问权限的客户)需要对应用执行某些操作时,用作指代应用的用户可读的标记。有关此内容的详细信息,将在利用 Azure AD 开发多租户 Web 应用程序一文中说明。

    • 访问类型:通过这一组单选按钮,你可以指定应用可以针对目录租户执行哪些操作。就本教程来说,我们的目标就是为应用配置 Web 登录,因此应选择“单一登录”

      note备注
      其他文章将深入介绍应用程序权限主题,但这里我们只会概述其背后的原理,因为你可能想要了解相关背景知识。

      Azure AD 使用称为 ServicePrincipal 的实体来表示应用程序。顾名思义,这些实体类似于你更为熟悉的用户主体,但应该用于描述应用程序。

      注册一个应用程序实际上就是在允许应用访问的目录实例的租户中创建应用程序的 ServicePrincipal

      向给定应用程序授予哪个访问级别取决于对应的 ServicePrincipal 所属的角色。在本演练中,你不需要选择读取和写入访问权限级别,但如果你要这样做,则注册流程会增加一些额外的步骤来收集更多信息,例如在执行此类查询时,要使用哪些密钥进行身份验证:在这种情况下,密钥也会存储在用于描述应用程序的 ServicePrincipal 中。使用 Graph API 查询 Azure AD 主题提供有关此内容的详细信息。

      通过应用程序注册过程授予的权限仅在访问目录本身时有效;这些权限并不用于确定其他 Azure 资源(如 SQL Azure 数据库、管理门户各部分及类似资源)的访问策略。

  3. 输入应用程序的名称并选择“单一登录”访问类型后,请单击右下角的箭头以移动到下一屏幕。

    应用程序属性 在此屏幕中,Azure 管理门户将收集服务在驱动登录协议流时所需的重要对等项。此处有你需要输入的内容:

    • 应用 URL:此参数表示 Web 应用程序的address。在此示例中,这对应于 https://localhost:44341/,即由 IIS Express 分配给你的应用程序的地址。如果到现在为止你都是完全按照说明进行操作的,那么该 URL 仍应保留在你的剪贴板上,可供你随时粘贴。 你输入的值在整个开发阶段都将有效:将应用程序部署到相应的过渡或生产环境后,你必须回到管理门户修改该地址,使之与新应用程序的位置相匹配。在本演练的后面部分,我们将讨论如何执行该操作。

      Warning警告
      Azure AD 需要知道你的应用程序的地址,这样当用户在 Azure AD 页上成功通过身份验证后,它就可以将流重定向回你的应用程序。

      必须事先提供此地址:不管 Azure AD 将身份验证流重定向到何种地址,都会给攻击者劫持身份验证流和窃取令牌造成方便。预先注册应用程序的 URL 可保证用于你的应用的身份验证令牌将只发送到你的应用。

    • 应用 ID URI:此参数表示 Web 应用程序的identifier。Azure AD 在登录时使用此值来确定该身份验证请求是否允许用户访问所有已注册应用程序中的这个特定应用程序,以便应用正确的设置。

    note备注
    应用 ID URI 必须在目录租户中唯一。此项有一个很好的默认值,即应用 URL 值本身,但这样使用时,不容易保持唯一性:在本地托管环境(如 IIS Express 和 Azure Fabric Emulator)中开发应用往往会生成有限的地址范围,这些地址将由多个开发人员甚至同一开发人员的多个项目重用。一种可行的策略是向应用 URI 值追加进行区分所需的内容。

    另请注意:应用 ID URI 是一个 URI,因此它不必对应于任何可通过网络寻址的终结点。这意味着,你可以选择与应用 URL 无关的内容:实际上,虽然在本教程中我们使用的是全新的应用程序,但你偶尔也会注册可能已具有自己的应用 ID URI(在此处使用的登录协议 WS-Federation 中,应用 ID URI 称为 realm)的现有应用程序,在这种情况下你可能想要在此处使用它。在利用 Azure AD 开发多租户 Web 应用程序主题中,我们将重点介绍多租户引入的一些附加约束。

  4. 输入应用 URL 和应用 ID URI 后,你可以单击右下角的复选框按钮。

    快速启动 这将结束注册过程,现在你的应用在目录租户中具有自己的条目,而 Azure AD 已准备好以自己的名义处理 Web 身份验证。

    通知你注册成功的屏幕为你提供了将 Web 应用程序配置为使用 Azure AD 进行登录所需的信息。即:“使用 Azure AD 启用单一登录”部分包含几个需要粘贴回 Visual Studio 的设置。

    让浏览器在此页上保持打开状态,然后切换回 Visual Studio 执行本演练的下一个任务。

由于 Azure AD 已准备好为应用程序颁发身份验证令牌,启用 Web 登录的最后一步是将应用程序本身配置为使用正确的身份验证协议处理请求。通过协议实施,应用程序可以在用户与应用进行的工作会话一开始就调用 Azure AD 和其他项目(特别是你的目录租户)来处理用户身份验证。

请务必在使用 Web 登录协议时,了解一些有关身份验证机制的背景信息。在高级部分中,你将找到更多详细信息。

我们选择的项目模板是 MVC 4 Intranet 应用程序。该模板通常依赖于 Windows 集成身份验证来确保对应用的用户进行身份验证。该机制在网络级别进行操作:它适用于 Intranet 上发布的任何服务,无需向应用程序本身添加任何身份验证逻辑。

当你在 Intranet 外部部署应用程序时(正如云应用的情况),将无法再依赖于网络级别的身份验证。在这些情况下,处理身份验证的最常见策略之一是:在应用程序前面添加某种中间件,该中间件会在更高级别重新创建必要的身份验证检查。此附加层可以负责拦截未经身份验证的请求、强制实施身份验证协议、将用户重定向到应用程序外部进行身份验证、向应用返回经过身份验证的用户的相关信息、管理会话以及通常情况下进行访问控制所需的所有任务。

此策略一致地应用于行业的所有选定平台、开发堆栈和登录协议;其在线路上的实施和编程模型各不相同,但一般模式会在很大程度上保持相同。

在本演练中,我们会将应用程序通过 WS-Federation 协议连接到 Azure AD:这仅是实现 Web SSO 的一个可能的选择,SAML-P 是另一个最常见的选择。

.NET Framework 4.5 以本机方式支持 WS-Federation:在 ASP.NET 应用程序的上下文中实施协议流、处理身份验证和处理会话所需的所有类均在盒子中提供。

简而言之:.NET 4.5 提供一组 HttpModule,后者应在应用程序的 HTTP 管道中进行实例化。这些模块旨在引用众所周知的配置节,这些节包含应用程序和验证机构(在此示例中为 Azure AD 租户)的协议对等项。当请求传入时,这些模块将对其进行检查,并根据需要实施身份验证协议:例如,收到未经身份验证的请求时,这些模块将从配置中读取 Azure AD 租户的对等项,使用这些对等项来撰写 WS-Federation 登录消息,并使用它将用户自动重定向以使用 Azure AD 进行身份验证。

note备注
.NET Framework 4.5 中专用于基于声明的标识相关任务的部分类称为 Windows Identity Foundation (WIF)。针对早期版本的 Framework(3.5 和 4.0)的应用也可以实施本演练中所述的步骤,但需利用在带外发布为独立库的 WIF 的早期版本(在此处下载)。不过请注意,分步说明会有所不同,因为这两个版本不完全兼容(类驻留在不同的命名空间中),而且你必须使用不同 Visual Studio 版本(2008 和 2010,在此处下载)的工具。

Visual Studio 2012 提供点工具和单击工具,这些工具可以帮助你将应用程序配置为使用 WS-Federation 进行 Web 登录:你可以使用工具的 UI 提供你所要信任的用于进行身份验证的机构的少量关键信息,然后工具就会发出相应的配置项。在本演练中,你只需编写很少的代码,因为相关工具将为你自动生成大部分代码。

  1. 你现在已了解我们将如何实现 Web 登录,接下来让我们使用标识和访问工具来配置应用程序。在解决方案资源管理器中,右键单击你的应用程序项目,然后从上下文菜单中单击“标识和访问...”

    标识和访问 Visual Studio 将显示下图所示的对话框。

    标识和访问提供程序 你将在当前显示的“提供者”选项卡中完成所有工作。鉴于本演练的目的,我们将忽略手头的任务不需要的所有选项。

  2. 该工具会列出可用于外包身份验证的各种机构类型。在我们的特定示例中,我们感兴趣的是使用“业务标识提供者”:单击相应的条目(从顶部数第二个选项)。

    标识和访问配置 当你选择该选项时,将在下方的面板中显示相应的 UI 元素。通过这些控件请求的信息与前面章节所述的应用程序注册过程结束时显示的条目完全匹配。此处有你需要输入的内容(从底部到顶部):

    • 输入应用程序的应用 ID URI(领域):此项是你在注册期间定义的应用程序的标识符。切换回显示管理门户的浏览器窗口,从“使用 App ID URI 更新代码”字段复制相应的值并将其粘贴在此处。

    • 输入 STS 元数据文档的路径:“STS 元数据文档”是一个文件,其中包含要连接到的权威机构的机器可读说明:工具将使用它来确定对登录流程(详见下文)很重要的参数的值。每个 Azure AD 租户都会公开一个此类文档,其位置在注册过程结束时提供。切换到管理门户,从应用注册页复制相应的值,切换回该工具,然后在此字段中粘贴该路径。

      note备注
      当你在文本框中粘贴元数据文档的路径时,该工具将显示关于证书无效的警告。这是因为元数据文档是使用自签名证书进行签名的,不是引发关注的原因。

    “确定”。该工具将访问指定的元数据文档,读取权威机构的对等项(用于登录的终结点地址、用于验证身份验证令牌签名的 X.509 证书、颁发的身份验证令牌的格式和版本,等等),并使用该信息来生成将应用程序连接到 Azure AD 所需的条目,然后将这些条目添加到 web.config

以下列表描述了通过该工具添加到 web.config 的主要条目。有关更详细的说明,请参阅本文档的高级部分。

  • system.identityModel 和 system.identityModel.services 的 <section> 条目:要使配置了解标识特定的配置设置,这些条目是必需的。

  • <system.web> 中的 <authorization> 设置:该工具会自动更改现有的 ASP.NET 身份验证设置,这样才能要求对每个向应用发出的请求进行身份验证。这将实施所谓的“全体重定向”行为,即将每个未经身份验证的请求都重定向到身份验证机构(而不是向未经身份验证的用户提供应用的一部分)。这种行为在 LoB 应用程序中是默认的。在这些应用程序中,鉴于用户已使用机构登录,身份验证往往是无提示的。如果开发人员要更改此行为以便按情况提供身份验证要求,可以相应地更改 <authorization> 设置。

  • <system.webServer/modules> 中的 WSFederationAuthenticationModule (FAM) 和 SessionAuthenticationModule (SAM):这些条目将添加到应用程序的 HTTP 管道 HttpModule 中,该管道负责强制使用 WS-Federation 进行身份验证。FAM 是负责协议实施的模块:登录请求、令牌验证注销管理是它负责的主要流程。SAM 处理会话:具体而言,它会生成会话 Cookie、验证它们并强制它们存在于每个请求中、处理会话的长度,等等。其行为由下文所述的配置元素驱动。

  • <system.identitymodel/identityConfiguration> 节:此元素确定应用在身份验证阶段的行为。例如:在子元素 ValidatingIssuerNameRegistry 中,它存储受信任的可提供身份验证服务的机构的列表,其方式是记录这些机构的名称及其用于签名的证书。

  • <system.identitymodel.services/federationConfiguration> 节:此节提供驱动 WS-Federation 流程所必需的对等项:要对登录请求使用的机构地址、要包含在请求中的应用本身的标识符,等等。

若要利用 Azure AD 进行 Web 登录,只需自动生成的配置即可:你无需在应用程序中编写任何身份验证特定的代码。 如果要访问用户身份信息,只需在当前主体中查询声明即可。例如,假设你要访问当前用户的姓名。你可以使用以下代码执行此操作,无需了解任何有关如何进行身份验证的信息:

//...
using System.Security.Claims;

namespace ExpenseReport.Controllers
{
  public class HomeController : Controller
  {
    public ActionResult Index()
    {            
      ClaimsPrincipal cp = ClaimsPrincipal.Current;
      string fullname = 
             string.Format("{0} {1}", cp.FindFirst(ClaimTypes.GivenName).Value,
             cp.FindFirst(ClaimTypes.Surname).Value);
      ViewBag.Message = string.Format("Dear {0}, welcome to the Expense Note App", 
                        fullname);
      return View();
     }
//...

从 .NET 4.5 开始,.NET 中的每个标识都使用 ClaimsPrincipal 表示。在此示例中,当前 ClaimsPrincipal 已在验证 Azure AD 生成的身份验证令牌期间构造好,并由用户在登录时提供。

每个 ClaimsPrincipal 均包含声明和特性的集合,这些特性说明当前用户已由身份验证机构验证。在我们的演练中,主体中的声明是令牌中由 Azure Active Directory 发出的声明:有关可用声明的完整列表,请参阅联机文档。

Azure AD 为经过身份验证的用户发出一组固定的声明。以下是 Azure AD 应该发出的所有声明的快速参考;你可以在文档中找到完整描述。

 

Type 示例中的值 说明

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier

S40rgb3XjhFTv6EQTETkEzcgVmToHKRkZUIsJlmLdVc

当前应用程序经过身份验证的用户的唯一不可变且不可重用的定向标识符

http://schemas.microsoft.com/identity/claims/objectidentifier

528b2ac2-aa9c-45e1-88d4-959b53bc7dd0

该用户在目录中的标识符。对于有关该用户的目录查询很有用。

http://schemas.microsoft.com/identity/claims/tenantid

cab1a5ac-f33b-45fa-9bf5-f37db0fed422

目录租户的标识符

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname

John

用户的名

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name

user@test04-realm2

用户的 UPN

http://schemas.xmlsoap.org/ws/2005/05/identity/claims/surname

Doe

用户的姓

http://schemas.microsoft.org/identity/claims/identityprovider

https://sts.windows.net/cab1a5ac-f33b-45fa-9bf5-f37db0fed422/

Web 登录协议(在此示例中为 WS_Federation)中表示的对用户进行身份验证的机构的标识符

至此,你的应用程序已具备使用 Azure AD 演示 Web 登录所需的所有条件,但是它还没有完成。你至少还需要添加两个重要功能:支持注销和自动刷新机构的协议对等项。

接下来的两节将详细介绍如何添加这两个功能:建议你在转到“运行你的应用”一节之前,先浏览这两节。

现今使用的 Web 登录协议通常包括执行分布式注销操作所需的设置:这些设置涉及各种流程,在这些流程中,当前应用程序不仅会取消其当前用户的会话,而且还会联系机构,指出应将注销命令传播到可能已由同一机构建立的所有其他应用程序的会话。WS-Federation 也不例外,它提供可在 WIF 的对象模型中完全实现的完整注销流程。在本小节中,我们将讨论如何将分布式注销功能添加到示例应用程序:这可以归结为在用户体验中提供正确的挂钩以触发注销流程,并生成要设置到 Azure AD 租户中的相应注销消息。

  1. 首先,将注销控制器添加到应用程序。你可以轻松执行该操作,方法是:在解决方案资源管理器中的项目下找到“控制器”文件夹,右键单击它并选择“添加”,然后单击“控制器”。将它命名为 SignOutController,选择“空的 MVC 控制器”(通常是默认设置),然后单击“添加”

  2. 我们将需要使用一些新程序集中的类,因此必须添加对这些程序集的引用。再次在解决方案资源管理器中,右键单击“引用”节点,选择“添加引用...”,在“搜索程序集”字段中键入 system.identitymodel.services,然后从主列表中选择相应的程序集。按“确定”

  3. 回到新创建的 SignOutController.cs 文件。向 using 指令添加以下条目:

    using System.IdentityModel.Services;
    using System.IdentityModel.Services.Configuration;
    
    现在更改 SignOutController 类的实现,如下所示:

    public ActionResult Index()
    {
        return View("SignOut");
    }
    
    public void SignOut()
    {
         WsFederationConfiguration fc = 
                FederatedAuthentication.FederationConfiguration.WsFederationConfiguration;
    
         string request = System.Web.HttpContext.Current.Request.Url.ToString();
         string wreply = request.Substring(0, request.Length - 7);
    
         SignOutRequestMessage soMessage = 
                         new SignOutRequestMessage(new Uri(fc.Issuer), wreply);
         soMessage.SetParameter("wtrealm", fc.Realm);
    
         FederatedAuthentication.SessionAuthenticationModule.SignOut();
         Response.Redirect(soMessage.WriteQueryString());
    } 
    
    
    以下是对该代码执行的操作的快速说明。

    • 第一个方法 Index() 处理 https://localhost:44341/SignOut 形式的请求。这是你稍后将在本演练的几个步骤中添加的视图地址。其目的是通知成功注销,我们将在下一个方法中这样使用它。

    • SignOut() 方法处理 https://localhost:44341/SignOut/SignOut 形式的请求,包含主要注销逻辑。

    • 第一行检索的对象由 WIF 用于跟踪 web.config 中的 WS-Federation 设置:我们将需要它来制作为当前应用程序定制的注销消息。

      note备注
      引用配置值(而不是对值进行硬编码或从自定义存储库获取值)通常是好的做法,因为这样做会使你的代码具有自适应性并与协议设置的其余部分保持一致:无论在部署前和部署后将配置文件中的设置更改了多少次,该逻辑都将有效。

    • 第二和第三行创建我们想要机构在注销流程结束时使用的返回地址。我们希望该地址指向前面讨论过的视图:因此,该代码将获取当前请求的 URL,并消除尾随的“注销”。从请求获取地址可保证正确解析客户端,而使用负载平衡器时,从托管层获取地址可能会导致内部端口问题。

    • 第四行传入机构的 URL 和前一行定义的返回地址,使用 WIF 制作 WS-Federation 注销消息。你可以轻松地直接在其线路窗体中创建消息,但是使用 WIF 对象模型将有助于编写更简洁的代码,并忽略大部分的语法详细信息。如果你有兴趣查看注销消息的样子,请确保在后面的一节中运行应用时捕获 HTTP 跟踪,或者在此处查阅规范。

    • 第四行将当前应用程序的标识符(如 <wsFederation> 配置元素的 realm 特性所记录的一样)添加到该消息。

    • 第 5 行使用 SAM(如前面自动生成的配置描述中所述)来清理本地会话:这包括删除登录时生成的会话 Cookie,以及任何可能必须进行的本地资源清理。

      note备注
      此处演示的示例应用程序并未执行很多操作,但实际的应用程序可能会在用户会话期间分配资源。如果是这样,你可以通过在 Global.asax 文件中添加相应的事件处理程序,利用 SAM 的 SigningOutSignedOut 事件来清理关闭会话后应处置的任何资源。

此处使用的视图将非常简单:如前所述,其目的只是为注销流程创建有意义的返回点。

  1. 解决方案资源管理器中,右键单击“视图”节点,然后添加“注销”文件夹。

  2. 通过右键单击该文件夹,然后依次单击“添加”“视图”在该文件夹中添加视图。也将新视图称为“注销”。将一些占位符表示代码放入视图文件 (SignOut.cshtml) 中,以便指示发生了注销。例如:

    @{
        ViewBag.Title = "SignOut";
    }
    
    <h2>You have successfully signed out</h2>
    
  3. 你可能还记得在前面的一节,我们将应用程序配置为通过全体重定向处理身份验证。这意味着,如果我们尝试在成功注销后访问此视图(这也是我们应该做的),我们将被立即重定向到 Azure AD 进行重新登录!为了避免该行为,你可以使用 web.config 中的 <location> 元素创建身份验证策略的一个例外。

    找到第一个出现的 <system.web> 元素,然后直接在它上方粘贴以下代码段:

      <location path="SignOut">
        <system.web>
          <authorization>
            <allow users="*" />
          </authorization>
        </system.web>
      </location>
    
    
    这是告诉 ASP.NET,注销路径可以由任何人访问,包括未经身份验证的用户。这项安排将允许你查看呈现在浏览器中的此视图,即使在成功注销后,也是如此。

  1. 至此,此应用已具有注销的功能,剩下的唯一要做的就是让此功能出现在用户体验中。此处提供一项非常简单的执行此操作的方法:在解决方案资源管理器中打开 Views\Shared 路径中的 _layout.cshtml。搜索字符串“Hello”以查找负责在典型的 MVC 4 布局顶部呈现登录信息的代码,然后修改登录部分,如下所示:

    <section id="login">
      @if (Request.IsAuthenticated)
      {  
        <text> Hello, <span class="username">@User.Identity.Name</span>! 
      @Html.ActionLink("Signout","SignOut", "SignOut")</text>
      }
      else {
        <text>  You are not authenticated </text>
      }
    </section> 
    
    

这将在登录用户的问候语右侧添加注销命令,以便从任何视图触发注销操作。

标识和访问工具已将应用程序配置为接受你选择的 Azure AD 租户的令牌。为了做到这一点,它在 web.config 中缓存了连接到预期的 Azure AD 终结点所需的协议对等项。而且,它还保存了在身份验证时用于验证传入令牌是否实际上源自 Azure AD 租户的关键信息:这些信息包括表示你的租户的颁发者名称,以及应该用于验证令牌签名的公钥(采用 X.509 证书的形式)。

定期更新加密密钥是常见的安全做法,Azure AD 签名密钥也不例外:旧密钥将在固定的时间间隔后停用,而新密钥将在颁发者的签名逻辑和你的租户的元数据文档中取代旧密钥。 在紧急情况下,可能会非周期性地更新密钥,显示很少的警告或不显示警告。

每次滚动签名密钥时,必须相应地更改应用程序设置:按照本演练中到目前为止显示的方法,这意味着重新运行工具以读取新的元数据文档并刷新 web.config 条目。

为了最大限度地减少停机时间,最好直接在应用程序中添加自我修复逻辑,这样便可通过编程方式使用元数据文档并对密钥滚动做出反应,而不需要操作员干预。下面是如何实现此功能的示例。

  1. 按照本文档前面所述,使用解决方案资源管理器添加对程序集 System.IdentityModel 的引用。

  2. 将以下 using 指令添加到 Global.asax 文件中:

    using System.Configuration;
    using System.IdentityModel.Tokens;
    
    
  3. 然后,在 Global.asax 文件中添加以下方法:

    //...
    protected void RefreshValidationSettings()
    {
        string configPath = AppDomain.CurrentDomain.BaseDirectory + "\\" + "Web.config";
        string metadataAddress = 
                      ConfigurationManager.AppSettings["ida:FederationMetadataLocation"];
        ValidatingIssuerNameRegistry.WriteToConfig(metadataAddress, configPath);
    }
    
    
    此处的逻辑很简单。ValidatingIssuerNameRegistry 是由标识和访问工具使用的类,其记录的信息涉及哪些机构受信任,以及应使用什么密钥来验证这些机构颁发的令牌。WriteToConfig 是一个静态方法,用于从元数据文档中读取颁发者设置(在此示例中是从配置检索的,在工具第一次运行时通过执行方法的第二行将它存储在配置中),并使用它在指定的路径(在方法的第一行从当前 AppDomain 构造)创建或更新文件的相应配置节。

  4. 若要在应用程序的生命周期中插入 RefreshValidationSettings(),请从 Application_Start() 调用它,如下所示。

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
    
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        RefreshValidationSettings();
    }
    
    Application_Start 调用 RefreshValidationSettings 可保证在安全时对 web.config 进行修改,但是如果你真的稍后在应用的生命周期中执行该操作,你会有触发刷新的风险。

Important重要提示
从应用程序自动刷新验证密钥时,需要应用一些额外的防范措施。需要规避的主要威胁是 DNS 劫持,在 DNS 劫持时,攻击者使用恶意软件将你指向恶意的元数据文档,并诱导你的应用信任错误的密钥。

如果你未重写用于处理 HTTP 请求的 .NET 默认设置,则由于元数据文档在 HTTPS 终结点上托管,将不会出现上述场景。DNS 劫持可能会将请求重定向到恶意的终结点,但这种终结点无法通过 HTTPS 服务器验证:由于并非实际拥有托管元数据文档的域,攻击者无法获取为该域颁发的证书,因此客户端将能够检测到服务器有问题,从而避免被误导。

有时,某些开发方案会要求你关闭 HTTPS 验证(通常通过 ServicePoint 类进行)。如果你使用本节中显示的自动元数据刷新逻辑,则在生产中部署应用程序之前还原 HTTPS 验证设置至关重要。

  1. 现在,我们终于能够观察运行中的应用程序了。按 F5:此时将打开一个浏览器窗口,该窗口将尝试访问在“创建 MVC 应用”一节的项目设置中指定的 URL。

    首先,你将收到证书错误。这是预期的行为,请单击“继续访问此网站(不推荐)”。在生产应用程序中不要忽略此错误,但出于本演练的目的,它是可以接受的。

    CertificateError 如果你一直在监视地址栏,可以观察应用的 URL 一小段时间;但是,在应用前面的 FAM 模块会立刻认识到调用未经过身份验证,并从配置中读取要执行的操作,然后触发将登录重定向到 Azure AD 的操作。会将 URL 地址栏替换为一个机构,并提示用户通过 Azure AD UI 进行身份验证。

    note备注
    如果你最初使用的是 Microsoft 帐户登录到管理门户,则你在前面创建的新用户帐户将不能用于管理 Azure 订阅。如果你在以新用户身份登录到应用程序后,尝试导航回管理门户,你将收到错误消息。你必须使用用于创建目录租户的帐户登录到管理门户。如果你最初使用 Azure AD 帐户登录到管理门户,并且已为你在前面创建的新用户授予“全局管理员”角色,则这个新用户可以管理你的 Azure 订阅。

    登录到 AAD
  2. 请输入在本演练第一节的 Azure 租户中创建的用户的凭据。按“登录”按钮。

    你可能还记得,当你在 Azure AD 租户中创建用户时,管理门户为该用户分配了临时密码。你必须使用该密码进行身份验证:但是,鉴于这种密码本来就是临时的,在第一次登录操作期间你必须选择适当的用户密码,然后才能继续执行身份验证流程。你完成该操作后,将恢复正常的应用程序登录流程。

    应用程序主页 当身份验证成功进行时,WIF 将处理传入身份验证令牌中的声明,而这些声明又将由主控制器中添加的简单显示代码使用。从现在起,你无需再次进行身份验证即可在整个站点中导航:每次回发将携带由 SAM 模块处理的会话 Cookie。

  3. 若要观察在终止会话时会发生什么情况,请单击右上角的“注销”链接。你将注意到,我们之前编码的重定向最终将停留在下面的视图上。

    注销 若要验证你是否确实已注销,请单击任何其他 UI 元素:身份验证周期将会重新开始。

本文档的演练部分显示了向 Web 应用程序添加 Web 登录所需执行的基本步骤。本文档的剩余部分将超出基础知识的范围,深入研究一些关键主题,并涵盖要使应用程序更上一个层次可能需要执行的一些其他任务。

在本节中,你将了解如何修改应用程序的设置,以便在 Azure 网站中部署和运行该应用程序。应用程序大体保持不变:唯一需要注意的是如何适应应用的新地址和会话管理。

本文档的此部分要求你拥有一个用于应用程序部署的 Azure 网站。如果你已有一个可用的网站,则可以使用它;如果没有,请参阅本文档以了解如何创建和发布 Azure 网站。如果你按照该文档中的教程进行操作,请在下载发布配置文件后立即停止:在部署应用程序之前,有几项内容需要调整。

在 Azure 管理门户中调整应用程序的设置

如果你回想关于应用程序注册的那一节,你会记得在 Azure AD UI 中定义应用程序的一个关键参数是应用程序本身的 URL。到目前为止的演练步骤都假定本地 IIS Express 作为应用的位置,但是部署到 Azure 网站意味着应用程序的 URL 将会更改,并且 Azure AD 中的设置将必须反映该更改。

  1. 导航回管理门户;选择左侧的 Active Directory 选项卡;单击你的目录租户;选择“应用程序”标题;单击你一直在使用的应用程序所对应的条目。单击“配置”标题;你将导航到一个屏幕,可以在其中修改你在创建时输入的应用程序设置。就本教程来说,请忽略屏幕的顶部区域,向下滚动到“单一登录”部分。

    单点登录
  2. 找到“答复 URL”文本框,并在该处输入目标 Azure 网站的地址(例如 https://aadga.windowsazure.net/)。这会让 Azure AD 在身份验证成功后将令牌返回到 Azure 网站位置(而不是你之前在线程中使用的开发时的位置)。更新该值后,请点击屏幕底部命令栏中的“保存”

note备注
你可能已注意到,应用 ID URI 仍在使用你在本文档前面部分创建的基于本地主机的值。

从技术上讲,只要该标识符采用 URI 形式并且在当前目录租户的所有应用中唯一,则对于此处讨论的应用类型来说,任何值都可以使用;这就是为什么主要说明未包括该值的更新操作的原因。

但是,出于可管理性目的,你可能需要修改应用 ID URI,使之携带更能代表你的应用程序的值。典型的示例是答复 URL 值的某些派生物。

请注意,如果你更改了应用 ID URI 值,则在部署之前需要将更广泛的更改应用于应用。更多详细信息在后面说明。

在 Azure 网站准备要运行的应用程序

大多数情况下,Web 登录配置已经云就绪:只有一个需要应用的更改,这主要是考虑到 Azure 网站的功能。

Web 登录过程会导致创建会话 Cookie,从身份验证即时启动后,每个请求都会发送该 Cookie。会话 Cookie 由 WIF 中间件创建,默认情况下它通过 DPAPI(请参阅本文档了解背景信息)进行签名和加密,以避免通过客户端进行的滥用(如更改声明列表以提升权限)。但是,Azure 网站中的 IIS 设置禁止使用 DPAPI 来保护会话,因此你需要更改 WIF 保护关联的 Cookie 的方式。.NET Framework 4.5 提供了现成的替代功能,该功能利用了 MachineKey(请参阅此处的文档),并且在 Azure 网站中使用时未出现问题。

标识和访问工具使此更改变得非常简单。

  1. 右键单击解决方案资源管理器中的项目,选择“标识和访问...”,然后选择“配置”选项卡。你会看到与以下屏幕截图类似的效果:

    标识和访问 Azure 网站
  2. 直接选中“启用 Web 场就绪 Cookie”标志并按“确定”。该工具会负责在 web.config 中添加必要的元素(在实际操作中,将默认类 SessionSecurityTokenHandler 替换为 MachineKeySessionSecurityTokenHandler),以便切换到 MachineKey,将其作为 Cookie 保护方法。

    note备注
    如果在前一步中更改了 Azure 管理门户中的应用 ID URI,则可以使用此 UI 轻松地将那些更改应用于你的项目:直接在顶部的两个文本字段中粘贴该应用 ID URI 值,然后点击“确定”。该工具会将那些更改应用到配置文件中的正确位置。

    (可选)你可能需要考虑通过在 web.config 文件的 <system.web> 节中添加条目 <customErrors mode="Off" />,暂时关闭 ASP.NET 自定义错误消息。如果你在部署时碰到问题,这将帮助你排查问题,但请确保在投入使用之前将这些设置重新打开:攻击者可能会利用详细的错误消息来探测你的应用的开口,而 customError 将防止这种情况发生。

这就是你需要执行的所有操作,目的是准备好你的应用程序,以便将其作为 Azure 网站运行。使用你的发布设置来部署应用程序,然后打开浏览器,浏览到应用的 azurewebsite.net 地址,然后按照本演练的应用测试部分所讨论的流程进行操作:由于我们将所有自定义逻辑设计为与位置无关,因此你可以执行在本地执行过的相同操作。

标识和访问工具会自动生成你的应用通过 WS-Federation 与 Azure AD 租户集成所必需的配置设置。在最佳情况下,你根本不需要实际查看这些设置;但是在某些场合,你需要变更默认行为,或者需要解决问题。在这种情况下,通过 WIF 配置设置查找适合你的方式可能会很有用。

Web 登录流程中使用的 WIF 类和方法已完全记录在 MSDN 中;在这里我们将提供经标识和访问工具修改后的 web.config 的批注版本。为了你的方便,我们还包括了从相关部分派生的更改,该部分内容是关于如何发布到 Azure 网站的。

note备注
为清楚起见,本文档提供完整的 Web.config 源代码,但仅对有关 WIF 的部分进行了批注。

<?xml version="1.0" encoding="utf-8"?>
<!--
  For more information on how to configure your ASP.NET application, please visit
  http://go.microsoft.com/fwlink/?LinkId=169433
  -->
<configuration>
  <configSections>
    <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />

上面的配置没有评论。

<section name="system.identityModel" type="System.IdentityModel.Configuration.SystemIdentityModelSection, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    <section name="system.identityModel.services" type="System.IdentityModel.Services.Configuration.SystemIdentityModelServicesSection, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />

在上面的配置中,此区域加载 ASP.NET 所需的类,目的是读取和解释 WIF 使用的配置节,从而为 WS-Federation 流程和身份验证设置建模。

  </configSections>
  <appSettings>
    <add key="webpages:Version" value="2.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="PreserveLoginUrl" value="true" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />

上面的配置没有评论。

    <add key="ida:FederationMetadataLocation" value="https://login.windows.net/ec4187af-07da-4f01-b18f-64c2f5abecea/federationmetadata/2007-06/federationmetadata.xml" />
    <add key="ida:Issuer" value="https://login.windows.net/ec4187af-07da-4f01-b18f-64c2f5abecea/wsfed" />
    <add key="ida:ProviderSelection" value="productionSTS" />
  </appSettings>

就上面的配置来说,这些 appSettings 条目由标识和访问工具捕获,以便跟踪不会保存在其他位置的重要设置(例如我们在密钥滚动更新节中使用的元数据文档的地址)。

  <location path="FederationMetadata">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>
  <location path="SignOut">
    <system.web>
      <authorization>
        <allow users="*" />
      </authorization>
    </system.web>
  </location>

就上面的配置来说,这两个 <location> 元素在 Web 应用程序中划分出了两个无需进行身份验证即可访问的区域(请参见下文)。FederationMetadata 节由标识和访问工具创建:该工具将创建描述应用程序的元数据文档,机构可以使用该文档来设置应用。在有关如何实现 Web 注销的说明中,你已自行添加 SignOut 节。

  <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5" requestValidationMode="4.5" />
    <!--Commented by Identity and Access VS Package-->
    <!--<authentication mode="Windows" />-->
    <authorization>
      <deny users="?" />
    </authorization>

就上面的配置来说,默认情况下,标识和访问工具设置 ASP.NET 身份验证和授权设置,使 Web 应用的每一部分(上面的例外除外)均需对用户进行身份验证,然后才能处理相关请求。虽然该配置通常适用于 LoB 应用,但有时开发人员需要保留可匿名访问的区域:如果你是这样的情况,请相应地更改此处的设置。

    <pages>
      <namespaces>
        <add namespace="System.Web.Helpers" />
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Optimization" />
        <add namespace="System.Web.Routing" />
        <add namespace="System.Web.WebPages" />
      </namespaces>
    </pages>
    <customErrors mode="Off" />
    <machineKey decryptionKey="998D0533DD570FDCA86A945893F0B2BFC0E1F3645E148F35" validationKey="E739C2EA4B4470820308DA71D81160F22C0D9CD3C97709CB0679E55FDCC2D35B35563D56102F254FB4908644ECB53B3898948F54AAC4A5F0C44754A5A997B79A" />
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />
    <handlers>
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
      <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>

上面的配置没有评论。

    <modules>
      <remove name="FormsAuthentication" />
      <add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
      <add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
    </modules>
  </system.webServer>

就上面的配置来说,此节中的条目在 SP.NET 管道中插入了 HTTPModule,以便实现核心协议和会话处理功能。WSFederationAuthenticationModule (FAM) 通过按协议规范验证传入令牌并生成发送到机构的登录消息,强制实施 WS-Federation。SessionAuthenticationModule (SAM) 与 FAM 合作创建并验证会话 Cookie。

  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-2.0.0.0" newVersion="2.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="WebGrease" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-1.3.0.0" newVersion="1.3.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
  <entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
      <parameters>
        <parameter value="v11.0" />
      </parameters>
    </defaultConnectionFactory>
  </entityFramework>

上面的配置没有评论。

  <system.identityModel>
    <identityConfiguration>
      <audienceUris>
        <add value="https://localhost:44342/ShiungZZZ" />
      </audienceUris>

就上面的配置来说,<system.identityModel> 包装所有 WIF 类特定的设置。它的第一个子元素 (IdentityConfiguration) 提供针对应用程序行为的与协议无关的描述。AudienceUris 列表提供当前应用程序的传入令牌中处于 WIF 接受范围内的所有值;通常情况下,这些值与应用程序的领域(或 Azure AD 中使用的应用 ID URI)相对应。传入令牌必须声明其预期的接收者是此处列出的值之一;如果情况并非如此,WIF 会认为这是被盗用的令牌,于是会拒绝调用。

           
      <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
        <authority name="https://sts.windows.net/ec4187af-07da-4f01-b18f-64c2f5abecea/">
          <keys>
            <add thumbprint="3A38FA984E8560F19AADC9F86FE9594BB6AD049B" />
          </keys>
          <validIssuers>
            <add name="https://sts.windows.net/ec4187af-07da-4f01-b18f-64c2f5abecea/" />
          </validIssuers>
        </authority>
      </issuerNameRegistry>

就上面的配置来说,ValidatingIssuerNameRegistry 元素包含可接受的颁发者名称-签名检查密钥元组的列表。在本演练中,这些设置将反映已关联到 Azure AD 租户的值:此元素可以保证其他颁发者(包括其他公司拥有的其他 Azure AD 租户)无法访问你的应用程序。

<certificateValidation certificateValidationMode="None">
      </certificateValidation>

就上面的配置来说,此元素将关闭 WIF 管道中的证书验证。在 Azure AD 示例中,由于使用自签名证书,这项措施是必要的:如果不在本地证书存储中安装证书本身,链验证或对等验证将失败。请注意:鉴于 ValidatingIssuerNameRegistry 会保证使用正确的证书,这并不会真正降低 Azure AD 身份验证的安全性;但是,如果你在同一应用中使用 WIF 来信任其他颁发者,请注意这些设置也会扩展到那些颁发者。

      <securityTokenHandlers>
        <add type="System.IdentityModel.Services.Tokens.MachineKeySessionSecurityTokenHandler, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
        <remove type="System.IdentityModel.Tokens.SessionSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </securityTokenHandlers>
    </identityConfiguration>

此节允许你操纵 WIF 用于处理传入安全令牌的类的集合(所谓的令牌处理程序)。它可用于影响个别处理程序的行为,或者用于添加和删除处理程序类型。在本示例中,该工具删除了默认的会话处理程序(该会话处理程序基于 DPAPI,不能在 Azure 网站上工作),将其替换为可与 MachineKey 配合使用的会话处理程序。

  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="false" />
      <wsFederation passiveRedirectEnabled="true" issuer="https://login.windows.net/ec4187af-07da-4f01-b18f-64c2f5abecea/wsfed" realm="https://localhost:44342/ExpenseReport" requireHttps="false" />
    </federationConfiguration>
  </system.identityModel.services>
</configuration>

就上面的配置来说,<system.identityModel.services> 用于存储 WS-Federation 特定的对等项。

具体说来,wsFederation 元素在这里用来记录 Azure AD 租户的 WS-Federation 登录终结点、在登录时要作为标识符发送的应用的领域(应用 ID URI),以及其他影响 WIF 的本地行为的标志,例如应用的 401 错误是否应始终触发向机构发送的登录消息 (passiveRedirectEnabled) 或是否应允许与清除 HTTP 相关的事务。

此元素可用于指定更多协议参数:这些只是保证登录流程正常运行所必需的参数。

本文档重点介绍一个范围相当窄的任务,即将 .NET 应用程序连接到 Azure AD 以通过 WS-Federation 执行 Web 登录。还有很多情况你都可以轻松对付,你可以使用各种不同的开放协议、利用任何现代化平台上的任何编程堆栈,或者直接在线路上的协议层进行操作。

在有关如何将应用部署到 Azure 的一节中,你已看到管理门户为你提供了更改应用程序注册设置的更多方面的机会:你将在此系列的下一个演练中了解这些附加控制中的大多数控制。在这里我们将只简要介绍若选择在协议级别与 Azure AD 交互,可如何获取所需的有关 Web 登录或它所支持的流程的任何其他操作的信息。

  1. 在浏览器窗口中打开 Azure 管理门户,然后导航到 Azure AD 部分中的“应用程序”标题。你将注意到屏幕底部的命令栏中包含一个条目:查看终结点。单击该条目。

    应用程序端点 该对话框列出了可通过编程方式与 Azure AD 租户进行交互的所有终结点。以下是对所有条目的简要说明:

    • 联合元数据文档: 将 Azure AD 租户描述为 Web 登录机构的元数据文档的位置。正如你在本演练中有关自动刷新密钥一节中已了解到的,本文档包含 WS-Federation 元数据对等项,并在同一包中包含 SAML 协议元数据。有关详细信息,请参阅Federation Metadata

    • WS-Federation 登录终结点:所有 WS-Federation 事务的入口点。这是你在本演练中用于登录流程和注销流程的终结点。有关详细信息,请参阅WS-Federation Endpoint URL

    • SAML-P 登录终结点: 用于在 SAML 协议中实现登录流程的终结点。有关详细信息,请参阅SAML Protocol Metadata and Endpoints

    • SAML-P 注销终结点:用于在 SAML 协议中实现注销流程的终结点。有关详细信息,请参阅SAML Protocol Metadata and Endpoints

    • Azure AD Graph 终结点:检索当前 Azure AD 租户中存储的目录信息的查询必须使用 Graph API 语法发送到此终结点。有关详细信息,请参阅使用 Graph API 查询 Azure AD

    • OAuth2 令牌终结点:此终结点用于服务器到服务器身份验证流程:例如,它可用于获取调用 Graph 终结点所需的访问令牌。有关详细信息,请参阅OAuth 2.0 (Preview Version)

社区附加资源

显示:
© 2014 Microsoft