如何处理“过期”的Firebase实例ID令牌

时间:2018-07-09 04:53:07

标签: firebase firebase-cloud-messaging

AFAIK,Firebase实例令牌将在以下4种情况下刷新:

(i)应用程序删除实例ID

(ii)应用已在新设备上还原

(iii)用户卸载/重新安装应用程序

(iv)用户清除应用数据

假设用户使用令牌A作为其“ FCM地址”。每次登录该应用程序时,他都会将令牌A与该用户的UUID一起注册到Firestore中,以便可以将特定于用户的云消息发送给他。他注销后,系统将向Firestore发出删除令牌A记录的请求。

现在,当用户重新安装应用程序时,实例ID会刷新并生成新的令牌B。令牌A变得无用。不幸的是,如果用户在卸载前未注销,则令牌A将永久保留在Firestore中。

有什么解决方法或更明智的方式来处理这种情况?

2 个答案:

答案 0 :(得分:10)

使令牌注册表保持最新需要两个步骤:

  1. 从应用程序代码中删除过时的令牌。
  2. 检查过时的令牌,并在发送消息时将其删除。

您的删除不再使用的令牌的方法是#1。

第二步是在尝试向其发送消息时收到messaging/invalid-registration-tokenmessaging/registration-token-not-registered响应时,从注册表/数据库中删除令牌。 functions-samples repo包含了一个很好的例子:

admin.messaging().sendToDevice(tokens, payload).then((response) => {
  // For each message check if there was an error.
  const tokensToRemove = [];
  response.results.forEach((result, index) => {
    const error = result.error;
    if (error) {
      console.error('Failure sending notification to', tokens[index], error);
      // Cleanup the tokens who are not registered anymore.
      if (error.code === 'messaging/invalid-registration-token' ||
          error.code === 'messaging/registration-token-not-registered') {
        // TODO: remove the token from your registry/database
      }
    }
  });
});

以上代码将Firebase Admin SDK用于Node.js,但相同的逻辑也可以应用于其他平台或通过HTTPS端点发送消息时。

答案 1 :(得分:0)

如弗兰克在回答中所提到的,您可以在发送邮件且未出现注册错误时将其删除。

这里是我在使用C#注册新的注册令牌时如何删除过时的注册令牌。

首先使用实例ID API ,我将获得令牌信息,如下所示:

 public async Task<FCMTokenInfo> GetTokenInfoAsync(string token)
    {
        try
        {
            HttpClient client = new HttpClient();

            client.BaseAddress = new Uri("https://iid.googleapis.com");
            client.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", String.Format("key={0}", "your-authorization-key"));

            var uri = $"/iid/info/{token}";

            var httpResponse = await client.GetAsync(uri);
            var responseStr = await httpResponse.Content.ReadAsStringAsync();

            if (httpResponse.StatusCode != HttpStatusCode.OK)
            {
                //log 400 bad request and do whatever you want
            }

            var result = JsonConvert.DeserializeObject<FCMTokenInfo>(responseStr);
            return result;
        }
        catch (Exception ex)
        {
            //log the exception
            throw;
        }
    }

FCMTokenInfo.cs

public class FCMTokenInfo
{
    public string Application { get; set; }
    public string Subtype { get; set; }
    public string Scope { get; set; }
    public string AuthorizedEntity { get; set; }
    public string Platform { get; set; }
}

然后在将注册令牌保存在数据库中的服务中:

//this method gets called when a new token is sent by the javascript web app
public async Task AddTokenAsync(Guid accountId, string token)
    {
        try
        {

            //getting TokenInfo of the current token(or refreshed one for that app)
            var fcmTokenInfo = await firebaseServices.GetTokenInfoAsync(token);

            //adding the current token
            dbContext.FcmRegisterationTokens.Add(new FcmRegisterationToken
            {
                Token = token,
                AccountId = accountId,
                AddingDate = DateTimeOffset.UtcNow,
                Application = fcmTokenInfo.Application,
                Subtype = fcmTokenInfo.Subtype,
                AuthorizedEntity = fcmTokenInfo.AuthorizedEntity,
                Scope = fcmTokenInfo.Scope,
                Platform = fcmTokenInfo.Platform
            });

            var outdatedTokens = await dbContext.FcmRegisterationTokens
                                         .Where(x => x.AccountId == accountId
                                                  && x.Application == fcmTokenInfo.Application
                                                  && x.Platform == fcmTokenInfo.Platform
                                         ).ToListAsync();

           //remove them
            dbContext.FcmRegisterationTokens.RemoveRange(outdatedTokens);

            dbContext.SaveChanges();
        }
        catch (Exception)
        {
             throw;
        }

    }