减少缺失订阅和更改通知
本文内容
在订阅的生存期内,Microsoft Graph 会发送特殊类型的通知,以帮助你最大程度地降低缺少订阅和更改通知的风险。 这些通知称为 生命周期通知 。
有三种类型的生命周期事件:
reauthorizationRequired 通知
订阅 删除 通知
错过的 通知
如果忽略这些事件,可能会中断更改通知流;可以通过在应用中实现逻辑来处理事件,以恢复连续的更改通知流。
本文介绍 Microsoft Graph 更改通知中的生命周期通知,并提供处理通知的指导。
支持的资源
虽然可以在任何资源类型上创建订阅时提供 lifecycleNotificationUrl ,但目前仅支持以下资源类型使用生命周期通知。
reauthorizationRequired 通知 - 所有资源
subscriptionRemoved 通知 - Outlook 消息 、Outlook 事件 、Outlook 个人 联系人 、Teams chatMessage
错过的通知 - Outlook 邮件 、Outlook 事件 、Outlook 个人 联系人
若要接收生命周期通知,必须在创建订阅时提供有效的 lifecycleNotificationUrl 终结点。
以下订阅创建请求定义了 notificationUrl 和 lifecycleNotificationUrl 终结点。
POST https://graph.microsoft.com/v1.0/subscriptions
Content-Type: application/json
{
"changeType": "created,updated",
"notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",
"lifecycleNotificationUrl": "https://webhook.azurewebsites.net/api/lifecycleNotifications",
"resource": "/users/{id}/messages",
"expirationDateTime": "2020-03-20T11:00:00.0000000Z",
"clientState": "<secretClientState>"
}
// Code snippets are only available for the latest version. Current version is 5.x
// Dependencies
using Microsoft.Graph.Models;
var requestBody = new Subscription
{
ChangeType = "created,updated",
NotificationUrl = "https://webhook.azurewebsites.net/api/resourceNotifications",
LifecycleNotificationUrl = "https://webhook.azurewebsites.net/api/lifecycleNotifications",
Resource = "/users/{id}/messages",
ExpirationDateTime = DateTimeOffset.Parse("2020-03-20T11:00:00.0000000Z"),
ClientState = "<secretClientState>",
};
// To initialize your graphClient, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=csharp
var result = await graphClient.Subscriptions.PostAsync(requestBody);
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
// THE CLI IS IN PREVIEW. NON-PRODUCTION USE ONLY
mgc subscriptions create --body '{\
"changeType": "created,updated",\
"notificationUrl": "https://webhook.azurewebsites.net/api/resourceNotifications",\
"lifecycleNotificationUrl": "https://webhook.azurewebsites.net/api/lifecycleNotifications",\
"resource": "/users/{id}/messages",\
"expirationDateTime": "2020-03-20T11:00:00.0000000Z",\
"clientState": "<secretClientState>"\
}\
'
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
import (
"context"
"time"
msgraphsdk "github.com/microsoftgraph/msgraph-sdk-go"
graphmodels "github.com/microsoftgraph/msgraph-sdk-go/models"
//other-imports
)
graphClient := msgraphsdk.NewGraphServiceClientWithCredentials(cred, scopes)
requestBody := graphmodels.NewSubscription()
changeType := "created,updated"
requestBody.SetChangeType(&changeType)
notificationUrl := "https://webhook.azurewebsites.net/api/resourceNotifications"
requestBody.SetNotificationUrl(¬ificationUrl)
lifecycleNotificationUrl := "https://webhook.azurewebsites.net/api/lifecycleNotifications"
requestBody.SetLifecycleNotificationUrl(&lifecycleNotificationUrl)
resource := "/users/{id}/messages"
requestBody.SetResource(&resource)
expirationDateTime , err := time.Parse(time.RFC3339, "2020-03-20T11:00:00.0000000Z")
requestBody.SetExpirationDateTime(&expirationDateTime)
clientState := "<secretClientState>"
requestBody.SetClientState(&clientState)
subscriptions, err := graphClient.Subscriptions().Post(context.Background(), requestBody, nil)
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
// Code snippets are only available for the latest version. Current version is 6.x
GraphServiceClient graphClient = new GraphServiceClient(requestAdapter);
Subscription subscription = new Subscription();
subscription.setChangeType("created,updated");
subscription.setNotificationUrl("https://webhook.azurewebsites.net/api/resourceNotifications");
subscription.setLifecycleNotificationUrl("https://webhook.azurewebsites.net/api/lifecycleNotifications");
subscription.setResource("/users/{id}/messages");
OffsetDateTime expirationDateTime = OffsetDateTime.parse("2020-03-20T11:00:00.0000000Z");
subscription.setExpirationDateTime(expirationDateTime);
subscription.setClientState("<secretClientState>");
Subscription result = graphClient.subscriptions().post(subscription);
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
const options = {
authProvider,
};
const client = Client.init(options);
const subscription = {
changeType: 'created,updated',
notificationUrl: 'https://webhook.azurewebsites.net/api/resourceNotifications',
lifecycleNotificationUrl: 'https://webhook.azurewebsites.net/api/lifecycleNotifications',
resource: '/users/{id}/messages',
expirationDateTime: '2020-03-20T11:00:00.0000000Z',
clientState: '<secretClientState>'
};
await client.api('/subscriptions')
.post(subscription);
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
<?php
use Microsoft\Graph\GraphServiceClient;
use Microsoft\Graph\Generated\Models\Subscription;
$graphServiceClient = new GraphServiceClient($tokenRequestContext, $scopes);
$requestBody = new Subscription();
$requestBody->setChangeType('created,updated');
$requestBody->setNotificationUrl('https://webhook.azurewebsites.net/api/resourceNotifications');
$requestBody->setLifecycleNotificationUrl('https://webhook.azurewebsites.net/api/lifecycleNotifications');
$requestBody->setResource('/users/{id}/messages');
$requestBody->setExpirationDateTime(new \DateTime('2020-03-20T11:00:00.0000000Z'));
$requestBody->setClientState('<secretClientState>');
$result = $graphServiceClient->subscriptions()->post($requestBody)->wait();
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
Import-Module Microsoft.Graph.ChangeNotifications
$params = @{
changeType = "created,updated"
notificationUrl = "https://webhook.azurewebsites.net/api/resourceNotifications"
lifecycleNotificationUrl = "https://webhook.azurewebsites.net/api/lifecycleNotifications"
resource = "/users/{id}/messages"
expirationDateTime = [System.DateTime]::Parse("2020-03-20T11:00:00.0000000Z")
clientState = "<secretClientState>"
}
New-MgSubscription -BodyParameter $params
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
from msgraph import GraphServiceClient
from msgraph.generated.models.subscription import Subscription
graph_client = GraphServiceClient(credentials, scopes)
request_body = Subscription(
change_type = "created,updated",
notification_url = "https://webhook.azurewebsites.net/api/resourceNotifications",
lifecycle_notification_url = "https://webhook.azurewebsites.net/api/lifecycleNotifications",
resource = "/users/{id}/messages",
expiration_date_time = "2020-03-20T11:00:00.0000000Z",
client_state = "<secretClientState>",
)
result = await graph_client.subscriptions.post(request_body)
请阅读 SDK 文档 ,了解如何将 SDK 添加 到项目并创建 authProvider 实例的详细信息。
lifecycleNotificationUrl 终结点可以与 notificationUrl 相同。
没有 lifecycleNotificationUrl 属性的现有订阅不会收到生命周期通知。 若要添加 lifecycleNotificationUrl 属性,应在创建订阅期间删除此类现有订阅并创建新订阅,同时指定属性。
使用 Webhook 传递通道时,必须 验证这两个终结点 。
生命周期通知的结构
生命周期通知有效负载遵循 changeNotificationCollection 的结构和相关 changeNotification 资源类型,如下所示:
{
"value": [
{
"subscriptionId":"<subscription_guid>",
"subscriptionExpirationDateTime":"2019-03-20T11:00:00.0000000Z",
"tenantId": "<tenant_guid>",
"clientState":"<secretClientState>",
"lifecycleEvent": "subscriptionRemoved or missed or reauthorizationRequired"
}
]
}
lifecycleEvent 可以是 subscriptionRemoved
、 missed
或 reauthorizationRequired
,表示生命周期通知类型。
生命周期通知不包含有关特定资源的任何信息,因为它与资源更改无关,而是与订阅状态更改相关。 与更改通知类似,生命周期通知可以批处理在一起,并作为集合接收,每个集合可能具有不同的 生命周期Event 值。 相应地批处理每个生命周期通知。
处理生命周期通知并恢复更改通知流时,更改通知将开始流向 notificationUrl 。
响应 reauthorizationRequired 通知
reauthorizationRequired
当 Microsoft Graph 要求应用重新授权订阅时,生命周期事件会发出警报,例如在以下情况下:
访问令牌即将过期时。
订阅即将过期 时。
当租户管理员撤销了应用读取资源的权限时。
在这些条件中的任何一个变为现实之前,Microsoft Graph 会向 lifecycleNotificationUrl 发送授权质询。
以下代码示例演示了 Microsoft Graph 更改通知服务如何计算这些通知的间隔。
//The following code is for illustrative purposes only
var TokenTimeToExpirationInMinutes=(TokenExpirationTime-CurrentTime)/4;
if((TokenTimeToExpirationInMinutes)<=180 && TokenTimeToExpirationInMinutes>60){
//Microsoft Graph will send reauthorizationRequired notification
TokenTimeToExpirationInMinutes=TokenTimeToExpirationInMinutes/2;
}
elseif(TokenTimeToExpirationInMinutes<60 && TokenTimeToExpirationInMinutes>=0){
//Microsoft Graph will send reauthorizationRequired notification every 15 mins
TokenTimeToExpirationInMinutes=TokenTimeToExpirationInMinutes-15;
} else {
//Microsoft Graph will stop sending reauthorizationRequired notifications
}
以下步骤代表活动的订阅的授权质询流:
Microsoft Graph 需要重新授权的订阅。
原因可能因资源而异,并可能随时间而变化。 若要维护订阅,必须响应重新授权事件,无论其原因如何。
Microsoft Graph 向 lifecycleNotificationUrl 发送授权质询通知。
更改通知的流可能会持续一段时间,从而提供额外的时间来做出响应。 但是更改通知传递将最终暂停,直至执行了所需操作。 当更改通知传递暂停以及应用再次成功创建订阅的时间时发生的任何有关资源更改的通知都将丢失。 在这种情况下,应用应单独提取这些更改,例如使用 增量查询 。
要采取的操作
通过使用响应代码响应 POST 调用 202 - Accepted
来确认生命周期通知的接收。
验证生命周期通知的真实性。
确保应用程序具有执行下一步操作的有效访问令牌。
调用下列两个API中的任意一个。 如果 API 调用成功,则更改通知流将继续。
调用 操作 /reauthorize
以重新授权订阅,而不延长其到期日期。
POST https://graph.microsoft.com/v1.0/subscriptions/{id}/reauthorize
执行常规的“续订”操作,以同时重新授权 和 续订订阅。
PATCH https://graph.microsoft.com/v1.0/subscriptions/{id}
Content-Type: application/json
{
"expirationDateTime": "2019-09-21T11:00:00.0000000Z"
}
如果应用不再有权访问资源,续订可能会失败。 然后,应用可能需要获取新的访问令牌才能成功重新授权订阅。
以后可以随时重试这些操作,例如访问条件发生变化时。
授权质询不能取代在订阅过期前续订订阅的需要。
访问令牌和订阅过期的生命周期并不相同。 你的访问令牌可能会在订阅之前过期。 请务必做好定期重新授权终结点以刷新访问令牌的准备。 重新授权终结点不会续订订阅。 但是, 续订订阅 也会重新授权终结点。
授权质询的频率可能会发生更改。
不要假设授权质询的频率。 这些生命周期通知会告知你何时采取措施,使你不必跟踪哪些订阅需要重新授权。 准备好处理从每个订阅每几分钟一次到某些订阅很少的授权质询。
响应 subscriptionRemoved 通知
subscriptionRemoved
当 Microsoft Graph 删除订阅时,生命周期事件会发出警报。 在这种情况下,如果要继续接收相关资源的更改通知,则需要重新创建订阅。
即使拥有长期订阅,访问资源数据的条件也可能会随时间而改变。 例如,服务中可能发生需要应用重新对用户进行身份验证的事件。 在这种情况下,Microsoft Graph 会向你发送 一个 subscriptionRemoved 通知。
以下流显示了 subscriptionRemoved 事件的流:
服务检测到需要从 Microsoft Graph 删除订阅。
这些事件没有设置节奏。 对于某些资源,它们可能经常发生,而对于其他资源,几乎永远不会发生。
Microsoft Graph 将发送 subscriptionRemoved
生命周期通知到 lifecycleNotificationUrl (如果指定)。
从发送生命周期通知到 subscriptionRemoved
应用成功重新创建订阅的时间段,没有生命周期通知可用。 应用需要自行提取这些更改。
要采取的操作
通过使用响应代码响应 POST 调用 202 - Accepted
来确认生命周期通知的接收。
验证生命周期通知的真实性。
确保应用程序具有执行下一步操作的有效访问令牌。
新建一个订阅。
此操作可能会失败,因为系统执行的授权检查可能会拒绝应用访问资源。 应用可能需要获取新的访问令牌才能成功重新授权订阅。 以后可以随时重试这些操作,例如,当访问条件发生变化时。
创建新订阅后,可以同步资源数据,以识别任何错过的更改通知;例如,使用 增量查询 。
响应错过的通知
missed
生命周期事件提醒你,某些更改通知可能尚未传递。 例如,由于 限制 。
要采取的操作
通过使用响应代码响应 POST 调用 202 - Accepted
来确认生命周期通知的接收。
验证生命周期通知的真实性。
执行资源的完整数据重新同步,以识别未作为通知传递的更改;例如,使用 增量查询 。
相关内容