在提供程序托管的低信任 SharePoint 加载项中处理安全令牌

重要

本文整体介绍如何在低信任授权系统(而非高信任系统)中使用安全令牌。 有关如何在高信任系统中使用令牌的信息,请参阅在提供程序托管的高信任 SharePoint 加载项中创建和使用访问令牌

使用低信任授权系统获取 SharePoint 数据的访问权限的 SharePoint 加载项会参与 OAuth 流,其中涉及在 SharePoint、Microsoft Azure 访问控制服务 (ACS) 和 SharePoint 加载项的远程组件(有时是用户的浏览器)之间传递安全令牌(格式为 JSON Web 令牌)。

重要

作为 Azure Active Directory (Azure AD) 的一项服务,Azure 访问控制 (ACS) 将于 2018 年 11 月 7 日停用。 此停用不会影响使用 https://accounts.accesscontrol.windows.net 主机名(不受此停用影响)的 SharePoint 外接程序模型。 有关详细信息,请参阅停用 Azure 访问控制对 SharePoint 外接程序的影响

有几种不同的工作流,具体取决于加载项的设计,但所有工作流均至少涉及下列两种令牌:

  • 访问令牌。 包含在加载项的远程组件向 SharePoint 发出的每个创建、读取、更新或删除 (CRUD) 请求者中。 SharePoint 验证令牌并提供请求。
  • 刷新令牌。 用于获取上下文令牌流中的优先访问令牌,并替换低信任授权系统的上下文令牌流和授权代码流中的过期访问令牌。

根据加载项所使用的 OAuth 流,此过程可能也包含下列两项内容之一:

  • 上下文令牌。 用于上下文令牌流中,向远程组件提供刷新令牌以及从 Azure ACS 请求访问令牌所需的信息。
  • 授权代码。 不是令牌,而是授权代码,对每个用户和应用程序对均具有唯一性。 在授权代码流中使用它获取优先访问令牌和刷新令牌。

访问令牌

在低信任授权系统中,访问令牌由 Azure ACS 创建并发送到 SharePoint 加载项的远程组件。 (在编写本文时,ACS 颁发的 SharePoint 访问令牌的有效期为 12 小时,这可能会发生变化。)SharePoint 外接程序中的代码需要实施的主要内容如下:

  • 从 Azure ACS 请求访问令牌。 根据所使用的 OAuth 流,加载项使用授权代码或它从上下文令牌提取的信息来发出请求。
  • 在对 SharePoint 的每个 HTTP 请求中包含令牌。 令牌添加为请求的 Authorization 标头。 标头的值为“Bearer”,后跟空格,然后是 Base 64 编码的基本访问令牌。
  • 缓存访问令牌,以便在后续请求中重复使用,这是可选操作,但建议这样做。
  • (可选)将访问令牌转发到后端系统,以便它们可以直接访问 SharePoint。

这些任务必须通过服务器端代码执行。 如果使用托管代码,某些任务的示例代码请参阅 Microsoft Visual Studio 的 Office 开发人员工具中的 SharePointContext.cs(或 .vb)和 TokenHelper.cs(或 .vb)文件。 有关执行部分任务的 PHP 代码示例,请参阅MSDN:SharePoint 2013 - 了解和使用 SharePoint REST 接口

缓存访问令牌

根据你的 SharePoint 加载项的体系结构和托管平台,有多种方法可以在服务器上缓存访问令牌:

注意

大多数情况下,将无法使用“AccessToken”这样简单的术语作为缓存密钥,因为你的加载项必须为不同的用户和 SharePoint 场/租赁保留令牌。 如果你的外接程序使用上下文令牌流,则有 SharePoint 提供的特殊 CacheKey 可用于区分缓存令牌。 本节介绍当你的应用程序不使用上下文令牌流时有哪些问题,以及如何处理这些问题。

在大多数情况下均可在会话状态下缓存访问令牌。 如果远程 Web 应用程序访问其他使用 OAuth (的服务,以及 SharePoint) 及其缓存会话状态中的各种访问令牌,请确保为令牌使用不同的缓存密钥:例如,使用“SharePoint_AccessToken”、“Facebook_AccessToken”、“SAP_Gateway_AccessToken”等,而不是“AccessToken”。 (如果不使用会话状态或其他会自动分离每个用户的缓存的其他缓存,则还需要对用户的键进行相对化处理。)

如果应用程序访问多个 SharePoint 场或在线租赁,可以将 SharePoint 域用作应用程序的主要缓存密钥 (SharePoint<mydomain>.sharepoint.com_AccessToken) 的一部分,或者使用服务器场/租赁的领域 (SharePoint<realmGUID>_AccessToken),这两者都可以从访问令牌读取。 (代码需要反转令牌的 Base 64 编码才能读取令牌。在托管代码中,TokenHelper.cs 或 .vb 文件具有用于此目的的示例代码,该代码使用 来自 Microsoft.IdentityModel.S2S.TokensSystem.IdentityModel.Tokens namespaces 的类。) 当应用程序使用上下文令牌流时,还有另一个选项可用,如下一段中所述。

在某些情况下,应用程序需要在跨会话或在会话结束之后对应用程序可用的某些位置缓存访问令牌。 例如,应用程序可能设计为允许用户将操作计划为在用户关闭应用程序之后执行。 如果这些操作包括访问 SharePoint,则加载项将需要检索访问令牌。 在这种情况下,应用程序必须为不同用户保存不同的访问令牌。

如果使用上下文令牌流,将在上下文令牌中提供用于此目的的缓存密钥字符串,外接程序启动后,SharePoint 会将此上下文令牌传递到 SharePoint 外接程序的远程组件。 有关此特殊缓存密钥以及如何使用它的详细信息,请参阅了解缓存密钥。 此外,还可将此字符串用于前一段中所述的情况。 计划系统具有多种方式来存储它要使用的配置数据,例如何时执行计划工作以及执行什么操作。 使用此存储保存用于访问令牌的缓存密钥。

如果使用的跨会话缓存也由多个应用程序共享,则必须将缓存密钥对应用程序、用户和 SharePoint 领域进行相对化处理。 在上下文令牌中提供的缓存密钥对应用程序、用户和 SharePoint 领域具有唯一性。

如果应用程序使用授权代码流,则说明没有上下文令牌,因此没有特制的缓存密钥。 在这种情况下,针对以下一项或多项进行相对化处理的缓存数据,将需要创建自己的键系统(具体取决于在应用程序的用例中可能发生什么潜在的命名冲突):用户、SharePoint 领域和应用程序。 可以将访问令牌内的声明用于此目的;例如,nameIdaud(请参阅下表)。 代码可以将字符串串联起来,或者将其作为种子来创建可作为缓存密钥的唯一哈希。

最后,如果你的应用程序同时对 SharePoint 进行仅加载项调用和用户+加载项调用,则有两种不同的访问令牌。因此,需要不同的缓存密钥。 确定基本缓存密钥后,只需向其追加“_add-in-only”或“_add+user”。

警告

将访问令牌存储在 Cookie 中并不是一种安全的做法。 避免将访问令牌通过浏览器传递通常是一种好的做法。

将访问令牌转发到后端系统

SharePoint 加载项的一些后端服务器可能未托管在与远程 Web 应用程序相同的域中。 当后端服务器需要在 SharePoint 上执行 CRUD 操作时,如果这些操作可以直接从后端系统进入 SharePoint,则加载项可以更快的速度执行。 幸运的是,仅当应用程序从 ACS 获取访问令牌时,域才重要。 具有令牌后,可将令牌转发给后端服务,然后这些服务可以使用它调用 SharePoint。

这些系统中的代码需要处理过期的访问令牌并将获取新访问令牌的请求发送回已在 ACS 中注册的父 Web 应用程序。(请参阅处理过期的访问令牌)。 该技术应该仅用于应用程序自己的后端服务,不用于外部 Web 服务。 此外,如果使用此技术,请考虑将后端服务设计为在所有可能的情况下使用仅外接程序调用。

处理过期的访问令牌

访问令牌将在几小时后过期(在本文编写时为 12 小时,但可能更改)。 如果应用程序在访问令牌过期后仍访问 SharePoint,过期后对 SharePoint 的第一个请求将导致 401 未经授权错误。 代码必须处理此响应。

代码也可以在使用之前测试访问令牌的过期时间。 代码使用刷新令牌从 ACS 获取另一个访问令牌。 在上下文令牌流中,刷新令牌包含在启动 SharePoint 的第一个会话时,你的加载项从 SharePoint 接收的上下文令牌中。 在授权代码流中,它将与优先访问令牌一起传递到应用程序。 代码必须将其缓存,使其在需要时可用。 刷新令牌将持续数月,并且可在 Cookie 或服务器端存储中保存。 有关详细信息,请参阅了解刷新令牌的处理和缓存

低信任授权系统的访问令牌示例

本节举例介绍了访问令牌,并说明在使用不同的授权策略时,它们有何区别。

用户+加载项策略

下面是 ACS 生成的用户+加载项访问令牌的解码示例,可用于使用用户+加载项策略对 SharePoint 进行调用。 已增加空格,方便阅读。 令牌符合 JSON Web 令牌协议。 令牌中的 JavaScript 对象表示法 (JSON) 对象称为声明集(有关声明集中属性的详细信息,请参阅表 1)。

所有值均须采用小写形式。 (用户+加载项访问令牌在上下文令牌流授权代码流中相同。)

{
 "aud": "00000003-0000-0ff1-ce00-000000000000/company.sharepoint.com@040f2415-e6e3-4480-96ce-26ef73275f73",
 "iss": "00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73",
 "nbf": 1377549246,
 "exp": 1377592446,
 "nameid": "2303000085ff9abc",
 "actor": "964de6ad-6d28-4dc7-8e05-3acd8006e5c9@040f2415-e6e3-4480-96ce-26ef73275f73",
 "identityprovider": "urn:federation:microsoftonline"
}

表 1: ACS 颁发的用户+加载项访问令牌声明

声明 说明 示例访问令牌中相应的值
aud “audience”的简写,表示令牌适用的主体。

格式为 audience principal ID/SharePoint domain@SharePoint realm,其中受众主体 ID 是 SharePoint 的永久安全主体 ID(请参阅 Microsoft 产品应用程序主体常量)。

SharePoint 领域为访问令牌用于访问的 SharePoint Online 租赁或本地 SharePoint 场的 GUID。 此 GUID 充当令牌颁发者的领域 ID,在本示例中为 Azure ACS。
00000003-0000-0ff1-ce00-000000000000/company.sharepoint.com@040f2415-e6e3-4480-96ce-26ef73275f73
iss “issuer”的简写。 它表示创建了令牌的主体。 格式为 Issuer GUID@SharePoint realm GUID。在低信任授权系统中,颁发者为 Azure ACS,其 GUID 为 00000001-0000-0000-c000-000000000000 00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73
nbf “not before”的简写。 它表示令牌生效的时间,自 1970 年 1 月 1 日午夜起计算的秒数。 默认情况下,该值设置为令牌创建的时间。(请参阅 JWT 时间值)。 1377549246
exp “expiration”的简写。 它表示令牌过期的时间。 默认情况下,这为 nbf 时间后 12 个小时(请参阅 JWT 时间值)。 1377592446
nameid 为其颁发令牌的用户的唯一标识符。 格式根据标识提供程序的不同而异。 在此示例中,提供程序是 Microsoft Online,但如果是 Active Directory,ID 将类似于 s-1-5-21-2127521184-1604012920-1887927527-415149 2303000085ff9abc
actor 需要 SharePoint 场或租赁的访问权限的主体。 它的格式为 Client ID of Application@SharePoint realm 964de6ad-6d28-4dc7-8e05-3acd8006e5c9@040f2415-e6e3-4480-96ce-26ef73275f73
identityprovider 在互联网号码分配局 (IANA) 注册的标识提供程序的唯一名称。对于安装到 SharePoint Online 的加载项,值通常与本示例中相同。 对于安装到本地场的加载项,通常为本地标识提供程序,例如 urn:office:idp:activedirectory urn:federation:microsoftonline

仅加载项策略

下面是 ACS 生成的仅加载项访问令牌的解码示例,可用于使用仅加载项策略对 SharePoint 进行调用。 已增加空格,方便阅读。 令牌符合 JSON Web 令牌协议。 有关声明集中属性的详细信息,请参阅表 2。 (仅外接程序策略不可用于使用授权代码流的应用程序,因为它们没有外接程序清单文件,因此无法请求使用仅外接程序调用的权限。)

{
 "aud":"00000003-0000-0ff1-ce00-000000000000/company.sharepoint.com@040f2415-e6e3-4480-96ce-26ef73275f73",
 "iss":"00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73",
 "nbf":1403304705,
 "exp":1403347905,
 "nameid":"c76da14e-07fd-4638-a723-1ff60ce70d63@040f2415-e6e3-4480-96ce-26ef73275f73",
 "sub":"1d47ac31-498b-4988-8aac-85fc9bd2e1ce",
 "oid":"1d47ac31-498b-4988-8aac-85fc9bd2e1ce",
 "trustedfordelegation":"false",
 "identityprovider":"00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73"
}

表 2:ACS 颁发的仅加载项访问令牌声明

声明 说明 示例访问令牌中相应的值
aud 与表 1 中的用户+加载项令牌相同。 00000003-0000-0ff1-ce00-000000000000/company.sharepoint.com@040f2415-e6e3-4480-96ce-26ef73275f73
iss 与表 1 中的用户+加载项令牌相同。 00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73
nbf 与表 1 中的用户+加载项令牌相同。 1403304705
exp 与表 1 中的用户+加载项令牌相同。 1403347905
nameid 加载项(而不是用户)的唯一标识符,因为用户的标识对于仅加载项策略并不重要。 格式为 client ID@SharePoint realm c76da14e-07fd-4638-a723-1ff60ce70d63@040f2415-e6e3-4480-96ce-26ef73275f73
sub “subject”的简写。 它是令牌的主题,即需要 SharePoint 的访问权限的主体;在本示例中,为远程 Web 应用程序。 对象 ID 用于此值。 请参阅 oid 声明。 1d47ac31-498b-4988-8aac-85fc9bd2e1ce
oid “object ID”的简写。 这是用于远程 Web 应用程序的 Azure Active Directory 中的对象 ID。 在仅外接程序访问令牌中,主题和对象 ID 为同一个值。 1d47ac31-498b-4988-8aac-85fc9bd2e1ce
trustedfordelegation 一个布尔值,用于指定 SharePoint 是否应该信任 SharePoint 外接程序来对用户进行身份验证和授权。 它在仅外接程序调用中为 false,因为用户标识并不重要。 false
identityprovider 标识提供程序的唯一名称。 因为它是提供了标识的外接程序,而不是用户,因此 ACS 是标识提供程序。 格式为 ACS GUID@SharePoint realm 00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73

上下文令牌

上下文令牌仅用于低信任授权系统的上下文令牌流。 当 SharePoint 加载项在 SharePoint 中启动时,SharePoint 请求 Azure ACS 创建上下文令牌,然后 SharePoint 会将其传递到 SharePoint 加载项的远程组件。 令牌在从 SharePoint 发出的对远程组件启动页面的请求中,作为隐藏的表单参数传递,称为 SPAppToken。 令牌使用仅对 ACS 和 SharePoint 加载项已知的客户端密码进行签名。

上下文令牌包括加载项使用的刷新令牌,以及上下文令牌中的其他信息,以便从 ACS 请求访问令牌。 (在编写本文时,ACS 颁发的 SharePoint 上下文令牌的有效期为 12 小时,这可能会变。)

SharePoint 加载项中代码的主要任务如下:

  • 使用加载项的客户端密码验证上下文令牌。
  • 缓存上下文令牌,或提取并单独缓存刷新令牌及其中的其他特定项目。
  • 使用刷新令牌和其他信息从 ACS 请求访问令牌(然后将其缓存)。
  • 从上下文令牌缓存 CacheKey。

重要

前两个任务必须在用户导航到其他页面或刷新页面之前执行,否则令牌将丢失。 例如,在 ASP.NET Web 窗体应用程序中,考虑使用 Page_Load 方法执行这些任务(在仅当请求不是回发时运行的条件代码块中)。 在 ASP.NET MVC 应用程序中,考虑使用默认的控制器方法执行这些任务。

如果你使用托管代码,某些任务的示例代码位于 Microsoft Visual Studio 的 Office 开发人员工具中的 SharePointContext.cs(或 .vb)和 TokenHelper.cs(或 .vb)文件。 您只需对 TokenHelper 类的成员进行简单调用。 例如,您的代码可以使用以下单行代码执行第一项任务:

SharePointContextToken contextToken =
    TokenHelper.ReadAndValidateContextToken(contextTokenString,
    Request.Url.Authority);

缓存上下文令牌或其中的一部分

可以缓存整个上下文令牌,或者仅缓存你的代码用于获取访问令牌的刷新令牌及其中的其他特定项目(位于服务器端或客户端缓存中)。 为简单起见,本文假定你将上下文令牌作为一个单元进行缓存。

重要

我们想再次提醒你,因为这一点的确非常重要:请勿对访问令牌使用客户端缓存。 安全的做法是仅将其用于上下文令牌。

你的服务器端缓存选项与上面为访问令牌列出的选项相同。 HTML 页面上的客户端选项包括 Cookie 和隐藏的窗体字段。 另一个选项是将上下文令牌存储在会话缓存中,但是将从其内部获取的 CacheKey 缓存在客户端上。

如果你的应用程序在会话结束后访问 SharePoint,那么会话缓存和客户端缓存都不可选择,因为如果在执行会话后工作时原始访问令牌已过期,刷新令牌必须对应用程序可用。 在这种情况下,需要由多个用户和/或 SharePoint 领域和/或应用程序共享的持久性(跨会话)缓存。 因此,你的代码必须使用可区分用户、SharePoint 领域和/或应用程序的缓存密钥,如上面的缓存访问令牌中所述。

可以将上下文令牌内部的特殊缓存密钥用于此目的,就像对访问令牌一样。(请参阅下面的了解缓存密钥部分。)

了解缓存密钥

缓存密钥是不透明的字符串,对用户、用户名颁发者、加载项和 SharePoint 场或 SharePoint Online 租户组合具有唯一性。 在加密之前,其格式如下,其中 Realm 是本地 SharePoint 场或 SharePoint Online 租赁的 GUID。

UserNameId + "," + UserNameIdIssuer + "," + ApplicationId + "," + Realm

缓存密钥不包含网站 URL 信息。 每个 SharePoint Online 租户(或本地 SharePoint 场)具有唯一领域,因此缓存密钥对每个用户名、用户名颁发者、应用程序和服务器场组合具有唯一性。 在下面的示例上下文令牌中,加密的缓存密钥值为:

KQAIUpDUD0sm5Tr83U+jZGYVuPPCPu8BGwoWiAACqNw=

由于你的应用程序可能会缓存多个项目,例如在具有相同缓存密钥的同一缓存中缓存访问令牌和上下文令牌,请考虑将缓存密钥作为词干,并根据需要附加或预置特定的字符串,例如“AccessToken”或“ContextToken”,以形成完整的缓存密钥。

另一个选项是为你想缓存的多项信息创建具有相应属性的类,然后缓存该类型的对象。

如果你使用数据库作为缓存,则还有第三个选项,即将表与 CacheKey 列和其他列一起用于缓存项目(AccessToken、ContextToken 等)。

当然,你的应用程序不一定要为其缓存的所有内容使用相同缓存。 常用模式是在会话缓存中缓存访问令牌,在数据库中缓存上下文令牌(或其内部的刷新令牌),在 Cookie 中缓存 CacheKey。

使用上下文令牌获取访问令牌

为获取访问令牌,您的应用程序直接向 ACS 发送请求。 请求包括从上下文令牌提取的三项信息(及其他信息):

  • 刷新令牌
  • SharePoint 的应用程序主体 GUID
  • 加载项希望访问的 SharePoint 场或 SharePoint Online 租赁的领域 GUID

TokenHelper.cs(或 .vb)文件具有创建此请求的代码。 有关执行此操作的 PHP 代码示例,请参阅 SharePoint:从 PHP 网站对 SharePoint 文档库执行操作

从上下文令牌进行分析的另一种方法是,应用程序可在运行时获取 SharePoint 租赁或场的领域。 如果使用托管代码,还可使用 TokenHelper.GetRealmFromTargetUrl 方法获取领域。 请务必缓存值,确保你的代码不会发出另一个网络调用重复获取域。

获取新的上下文令牌

如果需要新的上下文令牌(通常是因为包含在上下文令牌中的刷新令牌已过期),代码可以获取一个新的,方法是在每个 SharePoint 网站将浏览器重定向到一个特殊的页面 - AppRedirect.aspx。 必须将两个查询参数附加到此页面的 URL:

  • client_id:SharePoint 加载项的客户端 ID。
  • redirect_uri:获取新的上下文令牌后您希望浏览器重定向到的 URI。 SharePoint 会将上下文令牌发布到此 URI。 通常情况下,这是请求新的上下文令牌的相同页面、控制器方法或 Web 服务方法。 该值必须为 URL 编码。

下面显示了 URL 的结构:

https://<SharePointDomain> /_layouts/15/appredirect.aspx?client_id=<app_client_GUID> &amp;redirect_uri=<URL-encoded_redirect_URI>

下面是在使用 TokenHelper 文件的 ASP.NET 中发出请求的示例:

Response.Redirect(TokenHelper.GetAppContextTokenRequestUrl(sharePointUrl, Server.UrlEncode(Request.Url.ToString())));

上下文令牌示例

下面是一个上下文令牌示例。 顶部的小型 JavaScript 对象表示法 (JSON) 对象包含有关令牌的元数据。 这些属性与访问令牌中的属性相同(如上文所述)。 alg 属性的值是用于生成 ACS 附加到令牌的签名的算法名称。 有关令牌有效负载中属性的详细信息,请参阅表 3。 所有值均须采用小写形式。 已添加空格,方便阅读。

{"typ":"JWT","alg":"HS256"}
.
{
 "aud":"a044e184-7de2-4d05-aacf-52118008c44e/fabrikam.com@040f2415-e6e3-4480-96ce-26ef73275f73",
 "iss":"00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73",
 "nbf":"1335822895",
 "exp":"1335866095",
 "appctxsender":"00000003-0000-0ff1-ce00-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73",
 "appctx":"{
            \"CacheKey\":\"KQAIUpDUD0sm5Tr83U+jZGYVuPPCPu8BGwoWiAACqNw=\",
            \"SecurityTokenServiceUri\":\"https://accounts.accesscontrol.windows-int-sn1-004.accesscontrol.aadint.windows-int.net/tokens/OAuth/2\"
           }",
 "refreshtoken":"IAAAAC1Lv5w0OrcFAmJx0xk6aaBdhgsw3VPnPzNEDAWypTHtCYytZ2/dBBUKj+HLK8YB3IUCUfDxYpAque
NHKtgs4rYJJ5AegQpNMOJR1yYK8ngivQx0oetj7aSPuGVb+k6at6G0Kx5LZ5vhxkAq8iUSwu8p4L2cvNMzDF1mDKfMivqxgrIZkr2nbf9as0SJFL6VG5hZnDE4HKq
xJnejSW3umatKM4fsfY1MClVCxrkXb2EQ8H/TmwaJc388YW063GEVUS/3BTSgSIRBKQUmXJuJ6BZY7WTm84LaGrx3mIjnUTM/jnqPoPG55JbCC9sS/MeGNPtzPPCDg
6Vv7dVhQ1Dq5Y3fQ65e9LpJ580jCgzYYvpIFT+Wx5V+17mjY2T8wug04K2ts87Znsr+GfFCorf7NS/lj5HjoxRAQ2tva/8dwguSLwxcUwi/Q9MbpR0NNtlpwVazqi9O
hJ4Df7gVhUDdJ0Dtc6aFCPbl5ZLDDRs42xK2",
 "isbrowserhostedapp": "true"
}

audissnbfexp 声明与表 1 所述访问令牌中的声明完全相同。

appctxsenderappctxCacheKeySecurityTokenServiceUrirefreshtokenisbrowserhostedapp 声明如下表所述。

表 3. 上下文令牌声明和信息

声明 说明 示例上下文令牌中相应的值
aud a044e184-7de2-4d05-aacf-52118008c44e/fabrikam.com@040f2415-e6e3-4480-96ce-26ef73275f73
iss 00000001-0000-0000-c000-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73
nbf 1335822895
exp 1335866095
appctxsender “application context sender”的简写。 它表示将上下文令牌发送到 SharePoint 加载项的应用程序。 其格式为 GUID of principal@SharePoint realm,其中 GUID of principal 为应用程序主体的常量 ID,即 SharePoint、Exchange、Lync 或工作流。 00000003-0000-0ff1-ce00-000000000000@040f2415-e6e3-4480-96ce-26ef73275f73
appctx “add-in context”的简写。 它是包含 CacheKeySecurityTokenServiceURI 的 JSON 对象。 CacheKey:"KQAIUpDUD0sm5Tr83U+jZGYVuPPCPu8BGwoWiAACqNw=\", SecurityTokenServiceUri:"https://accounts.accesscontrol.windows-int-sn1-004.accesscontrol.aadint.windows-int.net/tokens/OAuth/2\"
CacheKey 可在任何键/值结构化缓存中用作键存储和检索上下文令牌的唯一值。 它还可以在数据库行中用作键列的值。 KQAIUpDUD0sm5Tr83U+jZGYVuPPCPu8BGwoWiAACqNw=
SecurityTokenServiceURI 令牌颁发服务的 URI。 https://accounts.accesscontrol.windows-int-sn1-004.accesscontrol.aadint.windows-int.net/tokens/OAuth/2
refreshtoken 加载项的刷新令牌。 IAAAAC1Lv5w0OrcFAmJx0xk6???
isbrowserhostedapp Boolean 字段指定对包含上下文令牌的外接程序的请求是来自浏览器 (true) 还是来自远程事件接收器 (false)。 true

使用上下文令牌将访问权限限制为仅 SharePoint 用户

如果要将远程组件(如 WCF 服务)的访问限制为 SharePoint 用户,则代码只需验证 HTTP 请求中的上下文令牌即可。 (如果使用托管代码,可以仅调用 TokenHelper.ReadAndValidateContextToken())。

如果想要确保它是 SharePoint(例如,不是 Exchange、Lync 或工作流),则代码可以验证令牌的参与者声明是否以 00000003-0000-0ff1-ce00-000000000000 开头。 如果你想执行需要回调 SharePoint 的其他验证操作,例如将访问限制到在 SharePoint 中担任特定角色的用户,请记住,你已为特定用户执行此验证(通过使用上下文令牌的 CacheKey),因此仅需执行一次此操作。

刷新令牌

刷新令牌包含在 SharePoint 在启动后发布到 Web 应用程序的上下文令牌中。 刷新令牌是 SharePoint 外接程序无法解密的已加密令牌。 当前访问令牌到期后,你的代码使用它以及其他信息获取新的访问令牌。 它还用于在上下文令牌流中获取优先访问令牌。 (在编写本文时,ACS 颁发的 SharePoint 刷新令牌的有效期为 6 小时,这可能会变更。)

访问令牌可持续数小时(当前为 12 小时),且最终用户每次从 SharePoint 启动 SharePoint 加载项时均会获取一个新的访问令牌,因此在下列情况之一,你只需要刷新令牌:

  • 用户在外接程序中具有运行时间较长的会话,在这些会话中,外接程序在启动后调用 SharePoint 数小时(当前超过 12 小时)。

  • 加载项的设计使用户能够将加载项计划为在会话结束后偶尔访问 SharePoint。

两种方案均要求你的加载项缓存刷新令牌,第二个方案要求服务器端缓存在会话之间具有持久性。 你的缓存选项与访问令牌中的选项相同,在上下文令牌流中,可以使用上下文令牌中的缓存密钥。 (在上下文令牌流中,只需缓存上下文令牌。它包含获取新访问令牌所需的刷新令牌和其他信息。在 授权代码流中,没有上下文令牌,因此缓存刷新令牌本身。)

如果通过外接程序在跨特定用户会话的存储中缓存刷新令牌,请务必将其替换为最新的刷新令牌。 在云托管的流和授权代码流中,用户在每次启动加载项时获取新的刷新令牌。

如果刷新令牌过期,向 ACS 发出新的访问令牌请求将导致 401 未经授权错误。 你的加载项应获取新的刷新令牌并使用它获取新的访问令牌,对此错误做出响应。 (由于刷新令牌已加密,你的代码无法在使用之前检查其过期日期。)

在上下文令牌流中,加载项通过获取新的上下文令牌获得新的刷新令牌。 在授权代码流中,加载项通过重新启动流获得新的刷新令牌。 具体而言,你的代码应该将用户重定向到 SharePoint OAuthAuthorize.aspx 页面,对此错误做出响应,如了解实时请求权限的加载项的 OAuth 流中所述。

授权代码

在授权代码流中,当请求 SharePoint 时,授权过程从 ACS 颁发的授权代码开始,然后 SharePoint 将其作为查询参数传递到远程应用程序 。 授权代码对每个用户和远程应用程序对均具有唯一性。 (在编写本文时,ACS 颁发的 SharePoint 授权代码的有效期为 5 分钟,这可能会变更。)

应用程序中的逻辑必须从查询参数获取授权代码,并使用它向 ACS 请求颁发访问令牌。 如果使用托管代码,创建令牌的示例代码位于 TokenHelper.cs(和 .vb)文件中。 读取查询参数的示例代码位于获取访问 SharePoint 的页面的后台示例代码。 ACS 在颁发访问令牌后立即将授权代码设置为无效,因此只能使用一次,且缓存它没有任何意义。

JWT 时间值

nbfexp 声明采用 JWT 规范指定的格式。 它们写入为自 1970 年 1 月 1 日以来的秒数。 在 C# 中,可以使用以下代码转换这些值,其中 jWTTimeStamp 是令牌中的值,例如 1335822895

DateTime exp = new DateTime(1970,1,1).AddSeconds(jWTTimeStamp);

对标记处理进行故障排除

免费的 Fiddler 工具可用于捕获你的加载项的远程组件发送到 SharePoint 的 HTTP 请求。 有一个工具的免费扩展,可自动解码请求中的令牌。

另请参阅