设置和配置 SharePoint Embedded

已完成

在本练习中,你将创建 Microsoft Entra ID 应用程序,在 Microsoft 365 SharePoint 租户上设置 SharePoint Embedded,并创建第一个容器类型和容器。

先决条件

注册 Microsoft Entra ID 应用程序

自定义 SharePoint Embedded 应用程序使用自定义 Microsoft Entra ID 应用程序进行身份验证并获取调用 Microsoft Graph 和 Microsoft SharePoint API 所需的权限。

打开浏览器并导航到 Microsoft Entra ID 管理员输入。 使用具有全局管理员权限的 Microsoft 365 租户 的工作或学校帐户 登录。

在左侧导航栏中选择“ 标识 > 应用程序 > ”“应用注册 ”,然后选择“ 新建注册”。

应用注册的 Microsoft Entra ID 管理中心的屏幕截图

“注册应用程序” 页上,按如下所示设置值,然后选择 “注册”:

  • 名称:SharePoint Embedded 应用
  • 支持的帐户类型:任何组织目录中的帐户 (任何 Microsoft Entra ID 租户 - 多租户)

注册应用程序页面的屏幕截图。

创建 SharePoint Embedded 应用程序后,Microsoft Entra ID 会显示新应用程序的详细信息。 创建一个文本文件,以跟踪稍后在本模块中需要的多个值。

应用程序 (客户端) ID & Directory (租户) ID 从应用的概述页复制到本地文本文件中。

新应用注册的应用程序和租户 ID 的屏幕截图。

配置身份验证

接下来,配置应用的身份验证设置。 从左侧导航栏中选择“ 管理 > 身份验证 ”,然后选择“ 添加平台”。

应用的“身份验证”页的屏幕截图。

选择 “Web ”选项,对于 “重定向 URI”,输入 https://oauth.pstmn.io/v1/callback 并选择“ 配置”。

接下来,选择“为新的 Web 平台添加 URI”,https://oauth.pstmn.io/v1/browser-callback然后选择“配置”。

本模块稍后将使用这两个选项通过 Postman 客户端进行身份验证和获取访问令牌。

将第二个重定向 URI 添加到 Web 平台的屏幕截图。

向下滚动到 “隐式授权和混合流 ”部分,选择“ 访问令牌 (用于隐式流) ”选项,然后选择“ 保存”。

通过选择“添加平台单页应用程序”添加另一个平台,并将“重定向 URI”设置为 http://localhost,然后选择“配置”。

配置 API 权限

接下来,使用更多权限配置应用,以便它可以创建和访问容器类型和容器。

注意

在发布时,必要的权限在 Microsoft Entra ID 管理中心的 API 选择器中尚不可见。 若要添加权限, FileStorageContainer.Selected 对于 Microsoft Graph 和 Container.Selected for SharePoint,需通过权限 ID 直接将它们添加到应用程序的清单中。

从左侧导航栏中选择“ 管理 > 清单 ”。 找到 属性 requiredResourceAccess 并对其进行编辑,使其类似于以下 JSON:

"requiredResourceAccess": [
  {
    "resourceAppId": "00000003-0000-0ff1-ce00-000000000000",
    "resourceAccess": [
      {
        "id": "4d114b1a-3649-4764-9dfb-be1e236ff371",
        "type": "Scope"
      },
      {
        "id": "19766c1b-905b-43af-8756-06526ab42875",
        "type": "Role"
      }
    ]
  },
  {
    "resourceAppId": "00000003-0000-0000-c000-000000000000",
    "resourceAccess": [
      {
        "id": "085ca537-6565-41c2-aca7-db852babc212",
        "type": "Scope"
      },
      {
        "id": "40dc41bc-0f7e-42ff-89bd-d9516947e474",
        "type": "Role"
      }
    ]
  }
],

重要

不要使用相同的 创建重复对象 resourceAppIds。 而是将其他对象添加到现有 resourceAppIds。 例如,如果 requiredResourceAccess 已将 设置为以下内容:

"requiredResourceAccess": [
 {
   "resourceAppId": "00000003-0000-0000-c000-000000000000",
   "resourceAccess": [
     {
       "id": "e1fe6dd8-ba31-4d61-89e7-88639da4683d",
       "type": "Scope"
     }
   ]
 }
],

将两个新权限添加到现有 "resourceAppId": "00000003-0000-0000-c000-000000000000" 对象,使其现在具有 3 (3) 权限。

某些权限需要管理员同意。 在左侧导航栏中选择“ API 权限” ,滚动到页面底部,然后选择链接“ 企业应用程序”。

在“权限”页上,选择“ 授予 Contoso 管理员同意”。 如果系统提示登录,请使用用于登录 Microsoft Entra ID 管理中心的同一 工作和学校 帐户。 在“ 请求的权限” 页上,选择“ 接受 ”以向管理员授予两对权限的同意: FileStorageContainer.Selected Microsoft Graph 和 Container.Selected for SharePoint。 这两对表示应用程序 & 两个权限中每个权限的委托选项。

创建客户端密码

若要使应用使用具有 Microsoft Entra ID 的 OAuth2 客户端凭据流进行身份验证,它需要客户端 ID 和客户端密码。

从左侧导航栏中选择“ 管理 > 证书 & 机密 ”。

“客户端密码” 部分中,选择 “新建客户端密码”。 添加说明并选择过期持续时间,然后选择“添加”

创建客户端密码后,会显示一次,因此请确保将其作为客户端密码复制到本地文本文件中,以供稍后在本模块中使用。 如果不复制此值,则将不得不创建新密码,因为永远无法查看以前创建的密码。

创建证书

与允许使用客户端 ID 和机密进行应用身份验证的 Microsoft Graph 不同,SharePoint 要求应用使用客户端 ID 和证书进行身份验证。 因此,我们现在需要创建一个证书。

以管理员身份打开 Windows PowerShell 提示符并运行以下 PowerShell 脚本。 出现提示时,输入证书的名称,例如 SharePoint Embedded:

$name = Read-Host -Prompt "Certificate name: "
$cert = New-SelfSignedCertificate -Subject "CN=$name" -CertStoreLocation "Cert:\CurrentUser\My" -KeyExportPolicy Exportable -KeySpec Signature -KeyLength 2048 -KeyAlgorithm RSA -HashAlgorithm SHA256
Export-Certificate -Cert $cert -FilePath "$name.cer"

# Private key to Base64
$privateKey = [System.Security.Cryptography.X509Certificates.RSACertificateExtensions]::GetRSAPrivateKey($cert)
$privateKeyBytes = $privateKey.Key.Export([System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob)
$privateKeyBase64 = [System.Convert]::ToBase64String($privateKeyBytes, [System.Base64FormattingOptions]::InsertLineBreaks)

# Private key file contents
$privateKeyFileContent = @"
-----BEGIN PRIVATE KEY-----
$privateKeyBase64
-----END PRIVATE KEY-----
"@

# Output to file
$privateKeyFileContent | Out-File -FilePath "$name.key" -Encoding Ascii

PowerShell 脚本会将证书 (*.cer) 和私钥 (*.key) 保存到执行 PowerShell 脚本的文件夹。

在 Microsoft Entra ID 管理中心,在应用的 “证书 & 机密 ”页上,选择“ 证书 ”,然后选择“ 上传证书”。

将新证书上传到应用的屏幕截图。

*.cer上传 PowerShell 脚本生成的 ,为证书提供说明,然后选择“添加”。

上传证书后,将显示的整个 指纹 复制到本地文本文件。

为 SharePoint Embedded 应用创建新的容器类型

下一步是为应用程序创建容器类型。

以管理员身份打开 Windows PowerShell 提示符。

安装或升级 SharePoint Online PowerShell 模块

如果之前尚未安装 SharePoint Online PowerShell 模块,请通过执行以下命令进行安装:

Install-Module "Microsoft.Online.SharePoint.PowerShell"

如果已安装它,请确保通过升级安装了最新的一个:

Upgrade-Module "Microsoft.Online.SharePoint.PowerShell"

注意

如果不确定是否已安装,请尝试执行第 Upgrade-Module 一个。 如果失败,则不会安装它,因此请 Install-Module 运行 cmdlet。

创建容器类型

安装最新的 SharePoint Online PowerShell 模块 后,下一步是在租户中创建容器类型。

更新以下 PowerShell 脚本中的以下值,然后执行脚本:

  • {{SPO_ADMIN_URL}}:这是 SharePoint Online 管理中心的 URL。 可以使用租户管理员帐户的工作和学校登录[https://portal.microsoft.com](https://portal.microsoft.com),选择左侧导航底部的“全部显示”,然后选择“管理中心 > SharePoint”来获取此权限。 复制 SharePoint 管理中心的 URL 并使用此值。 例如,如果租户 ID 为 Contoso123,则管理员 URL 将为 https://contoso123-admin.sharepoint.com
  • {{CONTAINER_TYPE_NAME}}:为新的容器类型选择一个名称。 例如,使用 FirstContainerType
  • {{AZURE_ENTRA_APP_ID}} 将此设置为之前创建的 Microsoft Entra ID 应用 ID(也称为“客户端 ID”)的值。 此值应位于本地文本文件中。
Import-Module "Microsoft.Online.SharePoint.PowerShell"
Connect-SPOService -Url "{{SPO_ADMIN_URL}}"
New-SPOContainerType -TrialContainerType -ContainerTypeName "{{CONTAINER_TYPE_NAME}}" -OwningApplicationId "{{AZURE_ENTRA_APP_ID}}"

PowerShell 脚本将显示新容器类型的详细信息,例如:

Container Type ID:
===============================================================================
ContainerTypeId     : 3a6b1fc4-0bd9-04b3-3a2a-4843fbb60914
ContainerTypeName   : FirstContainerType
OwningApplicationId : 763cd5ea-ade4-4d2a-a143-29498920e18f
Classification      : Standard
AzureSubscriptionId : 00000000-0000-0000-0000-000000000000
ResourceGroup       :
Region              :

ContainerTypeIdContainerTypeName 复制到本地文本文件以供以后使用。

将 Postman 配置为使用 Microsoft Entra ID 进行身份验证,以获取 Microsoft Graph 和 SharePoint Online 的委托和应用程序访问令牌

最后一步是在开发人员/提供商 Microsoft 365 租户中创建的新容器类型注册到使用租户。 这是使用 SharePoint REST API 完成的。 对于此步骤,你将使用 Postman 客户端。

使用 Postman 调用 SharePoint REST API 之前,需要先将 Postman 配置为获取访问令牌。

创建新的 Postman 环境

首先,创建一个新的 Postman 环境,该环境将存储环境变量以简化调用并集中所有设置。

在 Postman 中,选择“ 环境”,然后选择加号图标以创建新环境。

Postman 创建新环境的屏幕截图。

将环境命名为 SharePoint Embedded。

新 Postman 环境的屏幕截图。

将以下变量添加到环境中,并将 初始值 设置为本地文本文件中的 vales。 添加这些变量后,请保存环境。

变量 类型 注释 示例
ClientID 默认 以前在 Microsoft Entra ID 管理中心中创建的应用的客户端/应用程序 ID。 763cd5ea-ade4-4d2a-a143-29498920e18f
ClientSecret 秘密 以前在 Microsoft Entra ID 管理中心中创建的应用的客户端密码。 JXZ8Q........jbvanC
ConsumingTenantId 默认 租户/目录 ID (以前在 Microsoft Entra ID 管理中心中创建的应用的 GUID) 。 4c57ca2e-a63d-4999-9b69-610a7296e89b
RootSiteURL 默认 SharePoint Online 租户的 URL,不带尾部斜杠。 这与没有 -admin 字符串的 SharePoint Online 管理中心 URL 相同。 https://contoso123.sharepoint.com
ContainerTypeId 默认 之前创建的容器类型的 ID 3a6b1fc4-0bd9-04b3-3a2a-4843fbb60914
TenantName 默认 SharePoint Online 租户的 ID。 这是没有 -admin 字符串的 SharePoint Online 管理中心 URL 的第一部分。 contoso123
CertThumbprint 默认 之前为在 Microsoft Entra ID 管理中心中创建的应用上传的证书的指纹。 905EEA21C472368A36ADEDB26CCE6E760049BC1E
CertPrivateKey 秘密 证书私钥。 从先前执行的 PowerShell 脚本生成的 *.key 文件中复制全部内容,包括证书的-----begin 和结束分隔符。 ----BEGIN 私钥----- ... -----END 私钥---—
ContainerID 默认 将其留空。 稍后会使用它。

填充的 Postman 环境的屏幕截图。

通过在 Postman 客户端右上角的下拉选择器中选择环境来选择环境。 下拉列表位于齿轮和警报图标下方,以及选项卡所在的同一行上的 “保存共享 ”按钮上方。

创建新的 Postman 集合

接下来,创建一个新的 Postman 集合,用于存储请求并获取访问令牌。

在 Postman 中,选择“ 集合”,然后选择加号图标以创建新集合

将集合命名为 SharePoint Embedded。

在新集合中,使用集合的上下文创建到文件夹集,以存储 对容器的请求;一个在 委托 文件夹中,一个在 应用程序 文件夹中:

新 Postman 集合中文件夹的屏幕截图。

配置 Postman 集合的 Application 文件夹

下一步是更新 Application 文件夹的身份验证设置。 这需要更多工作,因为我们需要获取仅限应用的令牌才能调用 Microsoft Graph。 为此,需要配置 Application 文件夹以下载脚本,并将其存储在全局变量中供以后使用。

选择“ 应用程序 ”文件夹,然后选择“ 授权 ”选项卡。将 “类型 ”设置为 “持有者令牌 ”,并将 “令牌 ”设置为 {{AppOnlyCertGraphToken}}

注意

Postman 将显示验证错误,如下所示。 这是意料之中的,暂时可以忽略。 稍后将使用脚本创建此变量。

选择“ 请求前脚本 ”选项卡,然后输入以下脚本:

// download jsrsasign library and save it to a global variable
if (!pm.globals.has('jsrsasign-js')) {
  pm.sendRequest(
    'https://kjur.github.io/jsrsasign/jsrsasign-all-min.js',
    function (err, res) {
      if (err) {
        throw new Error(err);
      } else {
        console.log('Downloaded RSA library');
        pm.globals.set('jsrsasign-js', res.text());
      }
    }
  );
}

保存对集合所做的更改。

配置 Postman 集合的“应用程序 >容器” 文件夹

接下来,选择集合的 “应用程序 > 容器” 文件夹。

在“ 授权 ”选项卡上,将“ 类型 ”设置为 “继承父级的身份验证”。

在“ 请求前脚本 ”选项卡上,输入以下脚本:

async function ensureAccessToken () {
  var validToken = false;
  var token = pm.environment.get('AppOnlyCertGraphToken');
  if (token) {
    console.log('checking stored token');
    try {
      var tokenObj = KJUR.jws.JWS.parse(token);
      var nbf = tokenObj.payloadObj.nbf;
      var exp = tokenObj.payloadObj.exp;
      var now = getTimeInSec();
      if (nbf <= now && now < exp) {
        validToken = true;
      } else {
        console.log("Stored access token is expired");
      }
    } catch (e) {
      console.log("Unable to parse stored access token");
    }
  } else {
    console.log("No access token found");
  }
  if (!validToken) {
    acquireAccessToken();
  }
}

function acquireAccessToken() {
  console.log("Acquiring a new access token");
  var jwt = getRequestJwt();
  console.log(jwt);
  var tid = pm.environment.get('ConsumingTenantId');

  const tokenRequest = {
    url: `https://login.microsoftonline.com/${tid}/oauth2/v2.0/token`,
    method: 'POST',
    header: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: {
      mode: 'urlencoded',
      urlencoded: [
        { key: 'client_assertion_type', value: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' },
        { key: 'client_assertion', value: jwt },
        { key: 'client_id', value: pm.environment.get('ClientID') },
        { key: 'scope', value: 'https://graph.microsoft.com/.default' },
        { key: 'grant_type', value: 'client_credentials' }
      ]
    }
  };
  pm.sendRequest(tokenRequest, (error, response) => {
    if (error) {
      console.log('Unable to acquire token: ' + error);
    } else {
      var responseJson = response.json();
      var token = responseJson.access_token;
      if (!token)
        throw Error("Invalid or no access token received");
      pm.environment.set('AppOnlyCertGraphToken', token);
    }
  });
}

function getRequestJwt () {
  var header = {
    'alg': 'RS256',
    'typ': 'JWT',
    'x5t': safeBase64EncodedThumbprint(pm.environment.get('CertThumbprint'))
  };

  var now = getTimeInSec();
  var tid = pm.environment.get('ConsumingTenantId');
  var payload = {
    'aud': `https://login.microsoftonline.com/${tid}/oauth2/v2.0/token`,
    'exp': now + 60 * 60,
    'iss': pm.environment.get('ClientID'),
    'jti': pm.variables.replaceIn('{{$guid}}'),
    'nbf': now,
    'sub': pm.environment.get('ClientID'),
    'iat': now
  };

  var encryptedPk = pm.environment.get('CertPrivateKey');
  var decryptedPk = encryptedPk;
  if (pm.environment.has('CertPassword') && pm.environment.get('CertPassword') !== '') {
    decryptedPk = KEYUTIL.getKey(encryptedPk, pm.environment.get('CertPassword'));
  }
  var sHeader = JSON.stringify(header);
  var sPayload = JSON.stringify(payload);
  return KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, decryptedPk);
}

function getTimeInSec() {
  return Math.floor(Date.now() / 1000);
}

function safeBase64EncodedThumbprint (thumbprint) {
  var numCharIn128BitHexString = 128/8*2;
  var numCharIn160BitHexString = 160/8*2;
  var thumbprintSizes  = {};
  thumbprintSizes[numCharIn128BitHexString] = true;
  thumbprintSizes[numCharIn160BitHexString] = true;
  var thumbprintRegExp = /^[a-f\d]*$/;

  var hexString = thumbprint.toLowerCase().replace(/:/g, '').replace(/ /g, '');

  if (!thumbprintSizes[hexString.length] || !thumbprintRegExp.test(hexString)) {
    throw 'The thumbprint does not match a known format';
  }

  var base64 = (Buffer.from(hexString, 'hex')).toString('base64');
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

var navigator = {}; // fake a navigator object for the lib
var window = {}; // fake a window object for the lib
eval(pm.globals.get('jsrsasign-js'));
ensureAccessToken();

注意

此脚本将使用环境变量通过 Microsoft Entra ID 进行身份验证,以获取 Microsoft Graph 的仅限应用的令牌,并将其存储在名为 AppOnlyCertGraphToken的新变量或现有变量中。 必须使用脚本完成此操作,因为 Postman 不支持使用客户端证书而不是客户端密码的 OAuth2 客户端凭据流。

现在,从 应用程序 > 容器 文件夹运行请求时,请求的预脚本将获取令牌,更新在父 应用程序 文件夹的“授权”选项卡中设置的环境变量,然后执行请求。 由于请求位于 “容器 ”文件夹中,该文件夹的 “授权 ”选项卡设置为从父级继承,因此它将拾取重置的身份验证配置。

保存对集合所做的更改。

此时,Postman 现已配置为获取仅限应用的访问令牌,用于调用 Microsoft Graph。

向使用租户注册容器类型

配置 Postman 后,现在可以添加请求,将容器类型注册到使用租户。

在 Postman 中,从左侧导航栏中选择“集合”,展开“SharePoint Embedded > 应用程序”节点,选择“容器”节点上的“...”上下文菜单,然后选择“添加请求”。

将请求重命名为 “注册容器类型”。

将 HTTP 方法设置为 PUT 和以下终结点:

{{RootSiteURL}}/_api/v2.1/storageContainerTypes/{{ContainerTypeId}}/applicationPermissions

“预请求脚本”上,添加以下代码以获取仅限应用的令牌以调用 SharePoint REST API:

async function ensureAccessToken () {
  var validToken = false;
  var token = pm.environment.get('AppOnlyCertSPOToken');
  if (token) {
    console.log('checking stored token');
    try {
      var tokenObj = KJUR.jws.JWS.parse(token);
      var nbf = tokenObj.payloadObj.nbf;
      var exp = tokenObj.payloadObj.exp;
      var now = getTimeInSec();
      if (nbf <= now && now < exp) {
        validToken = true;
      } else {
        console.log("Stored access token is expired");
      }
    } catch (e) {
      console.log("Unable to parse stored access token");
    }
  } else {
    console.log("No access token found");
  }
  if (!validToken) {
    acquireAccessToken();
  }
}

function acquireAccessToken() {
  console.log("Acquiring a new access token");
  var jwt = getRequestJwt();
  console.log(jwt);
  var tid = pm.environment.get('ConsumingTenantId');

  const tokenRequest = {
    url: `https://login.microsoftonline.com/${tid}/oauth2/v2.0/token`,
    method: 'POST',
    header: {
      'Content-Type': 'application/x-www-form-urlencoded'
    },
    body: {
      mode: 'urlencoded',
      urlencoded: [
        { key: 'client_assertion_type', value: 'urn:ietf:params:oauth:client-assertion-type:jwt-bearer' },
        { key: 'client_assertion', value: jwt },
        { key: 'client_id', value: pm.environment.get('ClientID') },
        { key: 'scope', value: pm.environment.get('RootSiteURL') + '/.default' },
        { key: 'grant_type', value: 'client_credentials' }
      ]
    }
  };
  pm.sendRequest(tokenRequest, (error, response) => {
    if (error) {
      console.log('Unable to acquire token: ' + error);
    } else {
      var responseJson = response.json();
      var token = responseJson.access_token;
      pm.environment.set('AppOnlyCertSPOToken', token);
    }
  });
}

function getRequestJwt () {
  var header = {
    'alg': 'RS256',
    'typ': 'JWT',
    'x5t': safeBase64EncodedThumbprint(pm.environment.get('CertThumbprint'))
  };

  var now = getTimeInSec();
  var tid = pm.environment.get('ConsumingTenantId');
  var payload = {
    'aud': `https://login.microsoftonline.com/${tid}/oauth2/v2.0/token`,
    'exp': now + 60 * 60,
    'iss': pm.environment.get('ClientID'),
    'jti': pm.variables.replaceIn('{{$guid}}'),
    'nbf': now,
    'sub': pm.environment.get('ClientID'),
    'iat': now
  };

  var encryptedPk = pm.environment.get('CertPrivateKey');
  var decryptedPk = encryptedPk;
  if (pm.environment.has('CertPassword') && pm.environment.get('CertPassword') !== '') {
    decryptedPk = KEYUTIL.getKey(encryptedPk, pm.environment.get('CertPassword'));
  }
  var sHeader = JSON.stringify(header);
  var sPayload = JSON.stringify(payload);
  return KJUR.jws.JWS.sign(header.alg, sHeader, sPayload, decryptedPk);
}

function getTimeInSec() {
  return Math.floor(Date.now() / 1000);
}

function safeBase64EncodedThumbprint (thumbprint) {
  var numCharIn128BitHexString = 128/8*2;
  var numCharIn160BitHexString = 160/8*2;
  var thumbprintSizes  = {};
  thumbprintSizes[numCharIn128BitHexString] = true;
  thumbprintSizes[numCharIn160BitHexString] = true;
  var thumbprintRegExp = /^[a-f\d]*$/;

  var hexString = thumbprint.toLowerCase().replace(/:/g, '').replace(/ /g, '');

  if (!thumbprintSizes[hexString.length] || !thumbprintRegExp.test(hexString)) {
    throw 'The thumbprint does not match a known format';
  }

  var base64 = (Buffer.from(hexString, 'hex')).toString('base64');
  return base64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
}

var navigator = {}; // fake a navigator object for the lib
var window = {}; // fake a window object for the lib
eval(pm.globals.get('jsrsasign-js'));
ensureAccessToken();

在“ 授权 ”选项卡上,将 “类型 ”设置为“ 持有者令牌 ”,并将“ 令牌 ”设置为 {{AppOnlyCertSPOToken}}。 此令牌变量是在请求前脚本中创建和设置的。

在“ 正文 ”选项卡上,选择 原始 类型,将数据类型设置为 JSON ,并将以下代码添加到正文:

{
  "value": [
    {
      "appId": "{{ClientID}}",
      "delegated": ["full"],
      "appOnly": ["full"]
    }
  ]
}

注册容器类型请求的屏幕截图

选择“ 发送 ”按钮以执行 “注册容器类型” 请求。 Postman 将在请求下方显示响应:

在 Microsoft 365 使用租户中注册容器类型的成功响应的屏幕截图。

摘要

在本练习中,你创建了 Microsoft Entra ID 应用程序,在 Microsoft 365 SharePoint 租户上设置 SharePoint Embedded,并使用 PowerShell 创建第一个容器类型、一个新的 Postman 集合和关联的环境,用于向 Microsoft Graph 和 SharePoint REST API 提交请求。

知识检查

1.

以下哪项是 SharePoint Embedded 应用程序中容器类型的正确角色?

2.

在提供程序的租户中创建容器类型后,使用者租户管理员必须执行哪些操作?

3.

可在 SharePoint Embedded 中的容器级别应用哪些不同角色?