使用 Microsoft Graph 的最佳做法Best practices for working with Microsoft Graph

本文介绍可用于帮助你的应用程序充分利用 Microsoft Graph 的最佳做法,内容涉及了解 Microsoft Graph、提高应用性能,以及让应用程序对最终用户更具可靠性等。This article describes best practices that you can apply to help your applications get the most out of Microsoft Graph - whether that involves learning about Microsoft Graph, improving app performance, or making your application more reliable for end users.

使用 Graph 浏览器了解 APIUse Graph Explorer to get to know the API

开始探索可通过 Microsoft Graph 提供的数据的最简便方法是使用 Graph 浏览器The easiest way to start exploring the data available through Microsoft Graph is to use Graph Explorer. 通过 Graph 浏览器,你可以手动编写 REST 请求(带有完整的 CRUD 支持)、调整 HTTP 请求头,以及查看数据响应。Graph Explorer lets you craft REST requests (with full CRUD support), adapt the HTTP request headers, and see the data responses. 为了帮助你入门,Graph 浏览器还提供了一组查询示例。To help you get started, Graph Explorer also provides a set of sample queries.

在将它们集成到应用程序之前,请尝试使用新的 API。Experiment with new APIs before you integrate them into your application.

身份验证Authentication

要访问 Microsoft Graph 中的数据,应用程序需要获得一个 OAuth 2.0 访问令牌,并通过以下任一方式将其呈现给 Microsoft Graph:To access the data in Microsoft Graph, your application will need to acquire an OAuth 2.0 access token, and present it to Microsoft Graph in either of the following:

  • HTTP 授权请求头(作为一个持有者令牌)The HTTP Authorization request header, as a Bearer token
  • Graph 客户端构造函数(当使用 Microsoft Graph 客户端库时)The graph client constructor, when using a Microsoft Graph client library

使用 Microsoft 身份验证库 API (MSAL) 来获得 Microsoft Graph 的访问令牌。Use the Microsoft Authentication Library API, MSAL to acquire the access token to Microsoft Graph.

在应用中适用以下面向许可和授权的最佳做法:Apply the following best practices for consent and authorization in your app:

  • 使用最小特权Use least privilege. 只请求绝对必要的权限,并且只在需要时请求。Only request permissions that are absolutely necessary, and only when you need them. 对于应用程序调用的 API,查看方法主题中的权限部分(例如,查看创建用户),然后选择最小特权权限。For the APIs your application calls, check the permissions section in the method topics (for example, see creating a user, and choose the least privileged permissions. 有关权限的完整列表,请参阅权限引用For a full list of permissions, see permissions reference.

  • 根据应用场景使用正确的权限类型Use the correct permission type based on scenarios. 如果你正在构建交互式应用程序,其中存在一个已登录用户,那么应用程序应使用委派权限,在此权限中,应用程序被授权在调用 Microsoft Graph 时充当已登录用户。If you're building an interactive application where a signed in user is present, your application should use delegated permissions, where the application is delegated permission to act as the signed-in user when making calls to Microsoft Graph. 但是,如果应用程序在没有已登录用户的情况下运行(如后台服务或守护程序),那么应用程序应使用应用程序权限。If, however, your application runs without a signed-in user, such as a background service or daemon, your application should use application permissions.

    注意: 将应用程序权限用于交互式场景会将你的应用程序置于合规性与安全性风险中。Note: Using application permissions for interactive scenarios can put your application at compliance and security risk. 它可能会不小心提升用户权限来访问数据,绕过管理员配置的策略。It can inadvertantly elevate a user's privileges to access data, circumnavigating policies configured by an administrator.

  • 在配置应用时请考虑周全Be thoughtful when configuring your app. 这会直接影响最终用户和管理体验,以及应用程序的采用和安全性。This will directly affect end user and admin experiences, along with application adoption and security. 例如:For example:

    • 应用程序的隐私声明、使用条款、名称、徽标和域名都将出现在同意和其他体验中,所以一定要仔细配置,以便终端用户可以理解它们。Your application's privacy statement, terms of use, name, logo and domain will show up in consent and other experiences - so make sure to configure these carefully so they are understood by your end-users.
    • 考虑谁将同意你的应用程序(终端用户或管理员),并适当将应用程序配置为请求权限Consider who will be consenting to your application - either end users or administrators - and configure your application to request permissions appropriately.
    • 确保理解静态、动态和增量同意之间的区别。Ensure that you understand the difference between static, dynamic and incremental consent.
  • 请考虑多租户应用程序Consider multi-tenant applications. 预期客户有不同的应用程序和不同状态的同意控件。Expect customers to have various application and consent controls in different states. 例如:For example:

    • 租户管理员可以禁用最终用户同意应用程序的功能。Tenant administrators can disable the ability for end users to consent to applications. 在这种情况下,管理员需要代表他们的用户同意。In this case, an administrator would need to consent on behalf of their users.
    • 租户管理员可以设置自定义授权策略,如阻止用户读取其他用户的配置文件,或者将自助服务组创建限制为一组有限用户。Tenant administrators can set custom authorization policies such as blocking users from reading other user's profiles, or limiting self-service group creation to a limited set of users. 在这种情况下,应用程序应在代表用户操作的情况下处理 403 错误响应。In this case, your application should expect to handle 403 error response when acting on behalf of a user.

有效处理响应Handle responses effectively

根据你对 Microsoft Graph 发出的请求,应用程序应准备好处理不同类型的响应。Depending on the requests you make to Microsoft Graph, your applications should be prepared to handle different types of responses. 下面是一些要遵循的最为重要的做法,可确保应用程序能够可靠且可预测地为最终用户运行。The following are some of the most important practices to follow to ensure that your application behaves reliably and predictably for your end users.

分页Pagination

当查询资源集合时,应料到 Microsoft Graph 会在多个页面中返回结果集,这是由于服务器端页面大小限制所致。When querying a resource collection, you should expect that Microsoft Graph will the return result set in multiple pages, due to server-side page size limits. 当结果集跨多个页面时,Microsoft Graph 将在响应中返回 @odata.nextLink 属性,其中包含指向结果下一页的 URL。When a result set spans multiple pages, Microsoft Graph returns an @odata.nextLink property in the response that contains a URL to the next page of results.

例如,列出已登录用户邮件:For example, listing the signed-in users messages:

GET https://graph.microsoft.com/v1.0/me/messages

如果结果集超过服务器端页面大小限制,将返回包含 @odata.nextLink 属性的响应。Would return a response containing an @odata.nextLink property, if the result set exceeds the server-side page size limit.

"@odata.nextLink": "https://graph.microsoft.com/v1.0/me/messages?$skip=23"

注意: 应用程序应始终处理在本质上对响应进行分页的可能性,并使用 @odata.nextLink 属性获得下一个分页结果集,直到读取结果集的所有页面。Note: Your application should always handle the possibility that the responses are paged in nature, and use the @odata.nextLink property to obtain the next paged set of results, until all pages of the result set have been read. 最后一页将不包含 @odata.nextLink 属性。The final page will not contain an @odata.nextLink property. 你应在请求的 @odata:nextLink 属性中包括整个 URL,以获取下一页结果,将整个 URL 视为一个不透明的字符串。You should include the entire URL in the @odata:nextLink property in your request for the next page of results, treating the entire URL as an opaque string.

有关详细信息,请参阅分页For more details, see paging.

处理预期错误Handling expected errors

虽然应用程序应处理所有错误响应(在 400 和 500 范围内),但要特别注意某些预期的错误和响应,如下表所示。While your application should handle all error responses (in the 400 and 500 ranges), pay special attention to certain expected errors and responses, listed in the following table.

主题Topic HTTP 错误代码HTTP error code 最佳做法Best practice
用户无法访问User does not have access 403403 如果应用程序启动并运行,它可能会遇到此错误,即使它已经通过同意体验获得了必要的权限。If your application is up and running, it could encounter this error even if it has been granted the necessary permissions through a consent experience. 在这种情况下,最有可能的原因是登录用户没有权限访问所请求的资源。In this case, it's most likely that the signed-in user does not have privileges to access the resource requested. 应用程序应向登录用户反馈通用的“拒绝访问”错误。Your application should provide a generic "Access denied" error back to the signed-in user.
未找到Not found 404404 在某些情况下,可能无法找到请求的资源。In certain cases, a requested resource might not be found. 例如,资源可能不存在,因为尚未预配(如用户照片),或者因为已被删除。For example a resource might not exist, because it has not yet been provisioned (like a user's photo) or because it has been deleted. 一些已删除的资源可能在删除后的 30 天内完全恢复(如用户、组和应用程序资源),因此,应用程序也应该考虑到这一点。Some deleted resources might be fully restored within 30 days of deletion - such as user, group and application resources, so your application should also take this into account.
限制Throttling 429429 由于各种原因,API 可能会随时受限,因此,应用程序必须始终准备好处理 429 响应。APIs might throttle at any time for a variety of reasons, so your application must always be prepared to handle 429 responses. 此错误响应包括 HTTP 响应头中的**“重试后”字段。This error response includes the Retry-After field in the HTTP response header. 使用**“重试后”延迟退出请求是从限制中恢复的最快方法。Backing off requests using the Retry-After delay is the fastest way to recover from throttling. 有关详细信息,请参阅限制For more information, see throttling.
服务不可用Service unavailable 503503 这可能是因为服务繁忙。This is likely because the services is busy. 应部署类似于 429 的退出策略。You should employ a back-off strategy similar to 429. 此外,应始终通过新 HTTP 连接发出新的重试请求。Additionally, you should always make new retry requests over a new HTTP connection.

进化型枚举Evolvable enums

向现有枚举添加成员可能会造成客户端应用程序中断。Client applications can be broken by the addition of members to an existing enum. 对于 Microsoft Graph 中的一些较新的枚举,可以使用一种机制来添加新成员,而不会导致重大变更。For some newer enums in Microsoft Graph, a mechanism is available to allow for adding new members without incurring a breaking change. 在这些较新的枚举中,将显示一个常见的 sentinel 成员,称为 unknownFutureValue,它划分已知和未知枚举成员。On these newer enums, you'll see a common sentinel member called unknownFutureValue that demarcates known and unknown enum members. 已知成员的数量将少于 sentinel 成员,而未知成员的值将更大。Known members will have a number less than the sentinel member, while unknown members will be greater in value. 默认情况下,Microsoft Graph 不会返回未知成员。By default, unknown members are not returned by Microsoft Graph. 但是,如果编写的应用程序旨在处理未知成员外观,那么它可以通过 HTTP 首选请求头选择加入以接受未知枚举成员。If, however, your application is written to handle the appearance of unknown members, it can opt-in to receive unknown enum members, using an HTTP Prefer request header.

注意: 如果应用程序准备处理未知枚举成员,它应通过使用 HTTP 首选请求头选择加入:Prefer: include-unknown-enum-membersNote: If your application is prepared to handle unknown enum members, it should opt-in by using an HTTP prefer request header: Prefer: include-unknown-enum-members.

在本地存储数据Storing data locally

理想情况下,应用程序应调用 Microsoft Graph 来根据需要实时检索数据。Your application should ideally make calls to Microsoft Graph to retrieve data in real time as necessary. 只有在特定方案需要,且该用例被使用条款和隐私策略所涵盖,而且不违反 Microsoft Graph 使用条款 的情况下,在本地缓存或存储数据。You should only cache or store data locally if required for a specific scenario, and if that use case is covered by your terms of use and privacy policy, and does not violate the Microsoft Graph terms of use. 应用程序还应该实现适当的保留和删除策略。Your application should also implement proper retention and deletion policies.

优化Optimizations

一般来说,出于性能甚至是安全或隐私方面的原因,应只获取应用程序真正需要的数据,仅此足矣。In general, for performance and even security or privacy reasons, you should only get the data your application really needs, and nothing more.

使用投影Use projections

只选择应用程序真正需要的属性,仅此即可,因为这样可以在应用程序(和服务中)节省不必要的网络流量和数据处理。Choose only the properties your application really needs and no more, because this saves unnecessary network traffic and data processing in your application (and in the service).

注意: 使用 $select 查询参数将查询返回的属性限制为那些应用程序所需的属性。Note: Use the $select query parameter to limit the properties returned by a query to those needed by your application.

例如,检索登录用户的邮件时,可以指定仅返回 fromsubject 属性:For example, when retrieving the messages of the signed-in user, you can specify that only the from and subject properties be returned:

GET https://graph.microsoft.com/v1.0/me/messages?$select=from,subject

获取最少响应Getting minimal responses

对于某些操作,如 PUT 和 PATCH(在某些情况下还包括 POST),如果应用程序不需要使用响应有效负载,则可以要求 API 返回最小数据。For some operations, such as PUT and PATCH (and in some cases POST), if your application doesn't need to make use of a response payload, you can ask the API to return minimal data. 请注意,有些服务已向 PUT 和 PATCH 操作返回 204 无内容响应。Note that some services already return a 204 No Content response for PUT and PATCH operations.

注意: 在适当情况下,使用 HTTP 请求头请求最小表示形式的响应:首选:返回=最小Note: Request minimal representation responses using an HTTP request header where appropriate: Prefer: return=minimal. 请注意,对于创建操作来说,这可能不合适,因为应用程序可能期望在响应中获得新建对象的服务生成 idNote that for creation operations, this might not be appropriate because your application may expect to get the service generated id for the newly created object in the response.

跟踪更改:增量查询和 webhook 通知Track changes: delta query and webhook notifications

如果应用程序需要了解数据变化,只要你所感兴趣的数据发生更改,就会获得 webhook 通知。If your application needs to know about changes to data, you can get a webhook notification whenever data of interest has changed. 这比简单地定期轮询更为有效。This is more efficient than simply polling on a regular basis.

使用 webhook 通知,在数据发生变化时获得推送通知。Use webhook notifications to get push notifications when data changes.

如果应用程序需要在本地缓存或存储 Microsoft Graph 数据,并使这些数据保持最新,或者出于其他原因需要跟踪数据变化,则应使用增量查询。If your application is required to cache or store Microsoft Graph data locally, and keep that data up to date, or track changes to data for any other reasons, you should use delta query. 这样可以避免应用程序过度计算,以检索应用程序已有的数据,并最小化网络流量和降低达到限制阈值的可能性。This will avoid excessive computation by your application to retrieve data your application already has, minimize network traffic, and reduce the likelihood of reaching a throttling threshold.

使用增量查询以有效保持数据最新。Use delta query to efficiently keep data up to date.

结合使用 webhook 和增量查询Using webhooks and delta query together

webhook 和增量查询通常结合使用效果更佳,因为如果单独使用增量查询,则需要找出正确的轮询间隔,间隔过短可能会导致空响应进而浪费资源,而间隔过长可能最终会获得陈旧数据。Webhooks and delta query are often used better together, because if you use delta query alone, you need to figure out the right polling interval - too short and this might lead to empty responses which wastes resources, too long and you might end up with stale data. 如果使用 webhook 通知作为触发增量查询调用的触发器,将会两全其美。If you use webhook notifications as the trigger to make delta query calls, you get the best of both worlds.

使用 webhook 通知作为触发器以触发增量查询调用。Use webhook notifications as the trigger to make delta query calls. 此外,还应确保应用程序有一个支持轮询阈值,以防触发通知。You should also ensure that your application has a backstop polling threshold, in case no notifications are triggered.

批处理Batching

JSON 批处理使你能够通过将多个请求合并为一个单一 JSON 对象优化应用程序。JSON batching allows you to optimize your application by combining multiple requests into a single JSON object. 将各个请求合并到一个单独的批请求中,可以使应用程序不受严重网络延迟的影响,并且可以节省连接资源。Combining individual requests into a single batch request can save the application significant network latency and can conserve connection resources.

使用批处理时,严重的网络延迟会对性能产生很大的影响。Use batching where significant network latency can have a big impact on the performance.

可靠性和支持Reliability and support

若要确保可靠性并为应用程序提供支持:To ensure reliability and facilitate support for your application:

  • 接受 DNS TTL 并设置连接 TTL 以进行匹配。Honor DNS TTL and set connection TTL to match it. 这可确保在故障转移情况下的可用性。This ensures availability in case of failovers.
  • 打开到所有播发 DNS 答案的连接。Open connections to all advertised DNS answers.
  • 生成唯一的 GUID 并随每个 Microsoft Graph REST 请求发送。Generate a unique GUID and send it on each Microsoft Graph REST request. 如果需要报告 Microsoft Graph 的问题,那么这将有助于 Microsoft 更轻松地调查任何错误。This will help Microsoft investigate any errors more easily if you need to report an issue with Microsoft Graph.
    • 每次向 Microsoft Graph 发出请求时,会生成唯一的 GUID,将其随 client-request-id HTTP 请求标头发送,并将其记录在应用程序日志中。On every request to Microsoft Graph, generate a unique GUID, send it in the client-request-id HTTP request header, and also log it in your application's logs.
    • 始终记录 HTTP 响应标头中的 request-idtimestampx-ms-ags-diagnosticAlways log the request-id, timestamp and x-ms-ags-diagnostic from the HTTP response headers. 报告 Stack Overflow 中的问题或向 Microsoft 支持部门报告问题时,需要上述这些以及 client-request-idThese, together with the client-request-id, are required when reporting issues in Stack Overflow or to Microsoft Support.