目录架构扩展 | Graph API 概念
本主题介绍 Azure AD 图形 API 中的目录扩展,使用该图形 API 可将属性添加到目录对象,而无需任何外部数据存储。 例如,如果组织的某个业务线 (LOB) 应用程序要求目录中的每个用户都有一个 Skype ID,则可以使用图形 API 在目录的用户对象上注册新的名为 skypeId 属性,然后将一个值写入到特定用户的新属性。 本主题将帮助你了解目录扩展的限制,如何将它们注册到目录中,并提供它们在图形 API 中的用法示例。
重要
强烈建议使用 Microsoft Graph 代替 Azure AD Graph API 来访问 Azure Active Directory 资源。现在我们的开发工作将重点集中在 Microsoft Graph 上,没有计划对 Azure AD Graph API 进行进一步的改进。Azure AD Graph API 仍适用的方案数量非常有限;有关详细信息,请参阅 Office 开发人员中心中的博客文章 Microsoft Graph 或 Azure AD Graph。
扩展数据类型
只能使用 Graph API 1.5 版或更高版本注册扩展。 可以注册以下属性类型:
属性类型 | 备注 |
---|---|
Binary | 最多 256 个字节。 |
布尔值 | |
DateTime | 必须以 ISO 8601 格式指定。 将以 UTC 格式存储。 |
Integer | 32 位值。 |
LargeInteger | 64 位值。 |
字符串 | 最多 256 个字符。 |
可以在目录中的以下对象上注册上述属性类型:
了解扩展的注册方式
必须了解如何在目录中注册扩展属性,以及 Azure AD 的许可模型如何影响该属性的注册。 有关 Azure AD 中的应用程序许可的详细信息,请参阅将应用程序与 Azure Active Directory 集成中的同意框架概述。
扩展属性是在开发人员目录中的 Application 对象上注册的。 在应用程序已获得开发人员目录中的用户或管理员的许可后,该属性将添加到目标目录类型,并且立即可在开发人员目录中访问该属性。 对于多租户应用程序,如果另一组织中的用户或管理员向该应用程序授予了许可,则立即可以在另一组织的目录中的目标目录类型上访问这些扩展属性。
即使某个组织为包含已注册扩展的应用程序许可了“只读”权限,也仍可以在另一组织的目录中访问这些属性。 此外,扩展属性可由组织中任何已获许可的应用程序访问,而不仅仅是这些属性注册到的应用程序。 如果该组织中其他已获许可的应用程序具有足够的权限,则它们可以读取或写入新扩展属性的值。
如果在另一组织的目录中删除了该应用程序或许可,则将无法在目标目录对象上访问扩展属性。 如果应用程序删除了扩展,则将无法在目标目录对象上访问该扩展。 如果在授予许可后某个多租户应用程序添加了其他扩展属性,则在另一组织的目录中,将可以立即访问这些属性。
注意: 如果在某个对象上设置了某一扩展属性的值,并且在该对象的目录中无法访问该属性,则该属性仍将计入该对象的 100 个扩展属性值的限制。 已设置属性值后将该属性值排除在考虑之外的唯一方法是将其显式设为 null。 如果扩展属性不可访问,则无法执行此操作。
示例方案
考虑以下情景: Litware 是一家独立软件供应商 (ISV),现已开发一个 SaaS 应用程序供其他组织使用,此应用程序要求用户对象上存在名为 skypeId 的扩展属性。 Litware 首先在其自己的目录中注册该应用程序,然后调用图形 API 在 Application 对象上注册该扩展属性,这样,便可以在 Litware 的目录中的用户对象上访问该属性。 最后,Litware 使该应用程序支持多租户,使它能够在其他组织中使用。
Contoso 想要使用 Litware 的 SaaS 应用程序,以便 Contoso 的用户或管理员能够按许可使用该应用程序。 许可后,将在 Contoso 的目录中注册该应用程序,并且 Litware 为该应用程序注册的扩展属性将立即在 Contoso 目录中变为可用。 由于用户对象的 skypeId 扩展属性已由 Litware 在该应用程序上注册,因此可以在 Contoso 目录中的 User 对象上访问该属性。 Litware 的应用程序或 Contoso 目录中其他已获许可的应用程序现在可以根据为 Contoso 目录中的该应用程序配置的权限访问新属性。 这意味着应用程序根据其权限,可以在目录中的一个或多个用户上写入该扩展属性的值。 只有已写入 skypeId 值的用户将在其 User 对象上返回该属性。 除非将 skypeId 属性设为 null(在此之后,该用户的用户对象将不再返回该属性),否则将一直是这种情况。
目录扩展的示例 REST 请求
以下示例请求显示了如何在目录中注册、查看、写入、读取、筛选和注销扩展。 将 <applicationObjectId> 占位符替换为已注册的应用程序的对象 ID。 你可以按以下方式获取此值:
- 转到 https://graphexplorer.cloudapp.net/,单击右上角的“**Sign In**”(登录)链接,然后使用组织目录中管理员帐户的凭据登录。
- 登录后,单击资源文本框中的 URL(在“获取”按钮旁边),选择以 applications/ 结尾的 URL,然后单击“获取”,或单击 Enter 键。
- 在结果中查找所需的应用程序条目,然后复制其 objectId 值,如下所示: "objectId": "269fc2f7-6420-4ea4-be90-9e1f93a87a64"
本部分提供了以下操作的示例请求:
有关使用扩展属性的完整示例,请参阅 Github 上的 Azure AD 示例中的以下示例:
- WebApp GraphAPI DirectoryExtensions PHP: 演示如何使用 PHP 创建和使用扩展。
- WebApp-GraphAPI-DirectoryExtensions-DotNet: 显示 AAD 租户组织图,并允许直接读取现成的扩展值。
注册扩展
以下示例请求将在所需的 Application 对象上创建 extensionProperty。
请求格式
POST https://graph.windows.net/contoso.onmicrosoft.com/applications/<applicationObjectId>/extensionProperties?api-version=1.5 HTTP/1.1
{
"name": "<extensionPropertyName>",
"dataType": "<String or Binary>",
"targetObjects": [
"<DirectoryObject>"
]
}
示例请求
POST https://graph.windows.net/contoso.onmicrosoft.com/applications/269fc2f7-6420-4ea4-be90-9e1f93a87a64/extensionProperties?api-version=1.5 HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Content-Type: application/json
Host: graph.windows.net
Content-Length: 104
{
"name": "skypeId",
"dataType": "String",
"targetObjects": [
"User"
]
}
如果操作成功,则会返回“HTTP 201: 已创建”状态代码,以及完全限定的扩展属性名称,该名称可用于向目标类型写入值。
示例响应
HTTP/1.1 201 Created
...
{
"odata.metadata": "https://graph.windows.net/contoso.onmicrosoft.com/$metadata#directoryObjects/Microsoft.WindowsAzure.ActiveDirectory.ExtensionProperty/@Element",
"odata.type": "Microsoft.WindowsAzure.ActiveDirectory.ExtensionProperty",
"objectType": "ExtensionProperty",
"objectId": "dc893d45-a75b-4ccf-9b92-ce7d80922aa7",
"name": "extension_ab603c56068041afb2f6832e2a17e237_skypeId",
"dataType": "String",
"targetObjects": [
"User"
]
}
查看注册的扩展
以下示例请求将获取在 Application 对象上注册的扩展。
请求格式
GET https://graph.windows.net/contoso.onmicrosoft.com/applications/<applicationObjectId>/extensionProperties?api-version=1.5 HTTP/1.1
示例请求
GET https://graph.windows.net/contoso.onmicrosoft.com/applications/269fc2f7-6420-4ea4-be90-9e1f93a87a64/extensionProperties?api-version=1.5 HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Host: graph.windows.net
如果操作成功,则会返回“HTTP 200 正常”状态代码,以及有关在应用程序对象上注册的每个扩展属性的所有信息。
示例响应
HTTP/1.1 200 OK
...
{
"odata.metadata": "https://graph.windows.net/contoso.onmicrosoft.com/$metadata#directoryObjects/Microsoft.WindowsAzure.ActiveDirectory.ExtensionProperty",
"value": [
{
"odata.type": "Microsoft.WindowsAzure.ActiveDirectory.ExtensionProperty",
"objectType": "ExtensionProperty",
"objectId": "dc893d45-a75b-4ccf-9b92-ce7d80922aa7",
"name": "extension_ab603c56068041afb2f6832e2a17e237_skypeId",
"dataType": "String",
"targetObjects": [
"User"
]
}
]
}
写入扩展值
以下示例请求将在 User 对象上写入 *skypeId^ 扩展属性的扩展值。
请求格式
PATCH https://graph.windows.net/contoso.onmicrosoft.com/users/username@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
{
"<extensionPropertyName>": <value>
}
示例请求
PATCH https://graph.windows.net/contoso.onmicrosoft.com/users/jim@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Content-Type: application/json
Host: graph.windows.net
Content-Length: 65
{
"extension_ab603c56068041afb2f6832e2a17e237_skypeId": "jimbob.skype"
}
如果操作成功,则会返回“HTTP 204: 无内容”状态代码。
示例响应
HTTP/1.1 204 No Content
如果尝试的写入超过对象的 100 个扩展值限制,它将返回“HTTP 403 禁止访问”响应,其中包含错误代码“Directory_ResourceSizeExceeded”以及以下消息: “对象的大小已超出其限制。 请减少值的数目,然后重试请求”。
删除扩展值
以下示例请求通过将以前在 User 对象上为 skypeId 扩展属性设置的扩展值设置为 null 来删除该值。
请求格式
PATCH https://graph.windows.net/contoso.onmicrosoft.com/users/username@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
{
"<extensionPropertyName>": null
}
示例请求
PATCH https://graph.windows.net/contoso.onmicrosoft.com/users/jim@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Content-Type: application/json
Host: graph.windows.net
Content-Length: 65
{
"extension_ab603c56068041afb2f6832e2a17e237_skypeId": null
}
如果操作成功,则会返回“HTTP 204: 无内容”状态代码。
示例响应
HTTP/1.1 204 No Content
读取扩展值
以下示例请求将对用户执行简单的 GET 操作,从而返回标准的属性值及新的扩展属性值。
请求格式
GET https://graph.windows.net/contoso.onmicrosoft.com/users/username@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
示例请求
GET https://graph.windows.net/contoso.onmicrosoft.com/users/jim@contoso.onmicrosoft.com?api-version=1.5 HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Host: graph.windows.net
如果操作成功,则会返回“HTTP 200: 正常”状态代码,以及新的扩展属性值(为简洁起见,已从示例响应中删除了许多用户属性)。
示例响应
HTTP/1.1 200 OK
{
...
"usageLocation": null,
"userPrincipalName": "Jim@contoso.onmicrosoft.com",
"userType": "Member"
"extension_ab603c56068041afb2f6832e2a17e237_skypeId": "jimbob.skype"
}
筛选扩展值
以下示例请求将根据指定的扩展属性值筛选用户。
注意: 对于字符串搜索,扩展上的前缀搜索限制为 71 字符,二进制扩展上的搜索限制为 207 个字节。
请求格式
GET https://graph.windows.net/contoso.onmicrosoft.com/users?api-version=1.5&$filter=<extensionName>%20eq%20'<value>' HTTP/1.1
示例请求
GET https://graph.windows.net/contoso.onmicrosoft.com/users?api-version=1.5&$filter=extension_ab603c56068041afb2f6832e2a17e237_skypeId%20eq%20'jimbob.skype' HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Host: graph.windows.net
如果操作成功,则会返回“HTTP 200: 正常”状态代码,以及生成的用户对象。
示例响应
HTTP/1.1 200 OK
{
...
"usageLocation": null,
"userPrincipalName": "Jim@contoso.onmicrosoft.com",
"userType": "Member"
"extension_ab603c56068041afb2f6832e2a17e237_skypeId": "jimbob.skype"
}
注销扩展
以下示例请求将通过对扩展对象 ID 执行 DELETE 操作来注销某个扩展属性。
请求格式
DELETE https://graph.windows.net/contoso.onmicrosoft.com/applications/<applicationObjectId>/extensionProperties/<extensionObjectId>?api-version=1.5 HTTP/1.1
示例请求
DELETE https://graph.windows.net/contoso.onmicrosoft.com/applications/269fc2f7-6420-4ea4-be90-9e1f93a87a64/extensionProperties/dc893d45-a75b-4ccf-9b92-ce7d80922aa7?api-version=1.5 HTTP/1.1
Authorization: Bearer eyJ0eXAiOiJKV1Qi...r6Xh5KVA
Host: graph.windows.net
如果操作成功,则会返回“HTTP 204: 无内容”状态代码,并在应用程序中注销该扩展属性。
示例响应
HTTP/1.1 204 No Content
扩展行为和限制
以下行为和限制适用于目录中的扩展属性:
当目录用户或管理员向某个应用程序授予许可后,为该应用程序注册的扩展属性将在目录中变为可用。
扩展属性在目录中变为可用后,任何已获许可的应用程序将可以根据其在目录中的权限,为该属性适用的任何对象读取或写入该扩展属性的值。 扩展属性适用的对象在 targetObjects 属性中指定。
可以在一个目录中的特定对象上最多写入 100 个扩展属性值。 例如,假定尚没有其他扩展属性值已写入某个目录中的任何用户,如果某个应用程序将扩展属性值写入 user1,则该应用程序或目录中具有相应权限的其他应用程序可以将其他 99 个扩展属性的值写入到 user1;但是,目录中的其他用户仍将可以有最多 100 个扩展属性值写入到它们。
如果应用程序尝试在已设置 100 个扩展属性值的对象上设置其他扩展属性的值,Graph API 将返回 403 禁止访问响应,其中包含错误代码“Directory_ResourceSizeExceeded”和以下消息: “对象的大小已超出其限制。 请减少值的数目,然后重试请求”。
如果开发人员从应用程序中取消注册(删除)某个扩展属性,则该扩展属性将立即在开发人员目录中变为不可访问,并且也在已向该应用程序授予许可的目录中不可访问。
如果从开发人员目录中删除该应用程序,则已注册到该应用程序的所有扩展属性将立即在开发人员目录以及已向该应用程序授予许可的目录中变为不可访问。
如果已在目录中向某个多租户应用程序授予许可,然后该应用程序从该目录中取消注册(删除)- 例如,由管理员使用 Azure 管理门户执行操作,则在该应用程序中注册的任何扩展属性将立即在该目录中变为不可访问。
扩展属性值必须显式设为 null,才能从目录对象中删除。 如果在目录对象上设置了某个扩展属性值,但由于上面提到的任何原因,该扩展属性在目录中变为不可访问,则该扩展属性将不再在该目录对象上可见。 但是,它仍将计入该对象的 100 个扩展属性值限制。 除非恢复该扩展属性的可用性(例如,在某些情况下,通过再次对应用程序授予许可),否则将无法对该值进行读写访问。