Web Push API - 在后端存储订阅信息

11

我已经按照谷歌教程https://developers.google.com/web/fundamentals/getting-started/codelabs/push-notifications/实现了Web Push API。

这个教程包括一种方法,可以用来将订阅推送到后端服务器:

function updateSubscriptionOnServer(subscription) {
  // TODO: Send subscription to application server
  ...
}

我想将订阅与用户标识一起存储,以便可以选择要发送通知的用户。现在我在想,我需要将订阅的哪个部分存储在数据库中。我的订阅对象看起来像这样:

{"endpoint":"https://fcm.googleapis.com/fcm/send/...","keys":{"p256dh":"...","auth":"..."}}

我应该只创建一个包含(Id|User_Id|Subscription)列的“订阅”表格,其中包括整个JSON订阅吗?这是最佳实践吗? JSON的有效性是无限的吗?在取消订阅的情况下,我可以使用哪个字段来标识订阅?


我正在存储整个JSON,但是当用户取消订阅时,我也不知道如何删除订阅行。 - Flimm
3个回答

6
为了让匿名的网络推送用户使用我们的服务,我们想出了一个方法,即对订阅进行哈希处理,并将哈希作为后端的主键(ID)。
// pseudo-code
const id = hash(subscription);
https.post(`${SERVER}/subscription/${id}`, subscription).then(...);

据我正确理解,订阅不会随着时间变化而改变,因此哈希是一个常量。由于每个订阅都是唯一的,您可以选择适当的哈希函数(例如SHA-512),因此不应该出现冲突。
然后,只要您可以访问原始订阅并重新创建哈希/ID,就可以在Service Worker中重新验证订阅或处理pushsubscriptionchange事件。
这应该涵盖大多数情况。但是,在通过Google和Firefox的推送服务器发送推送通知时,您仍然需要尊重无效订阅的响应代码(HTTP 401),并将其从数据库中删除。
有关可用哈希函数,请参见JavaScript加密功能。支持FF和Chrome。

1
该标识符在您需要区分来自同一用户在不同设备上的多个订阅时也很方便。设备将发送哈希值,然后更新特定订阅的数据库中的“lastSeen”字段。稍后,我可以使用它来删除非活动订阅。 - Jette
如果某个特定用户决定向用于保存订阅的后端服务器端点发送多个订阅,从而淹没数据库,会发生什么?这里的控制机制是什么? - astralmaster
你要哈希PushSubscription的哪一部分?整个对象还是只有端点URL?此外,你在哪里读到订阅不会随时间改变?这是规范的一部分吗? - Mikey

4

将订阅信息存储在数据库中

如果您使用文档数据库,则您的数据库应该如下所示:

userId: {type:String, required: true},
endpoint: { type: String, unique: true},
keys: {
 p256dh: {type: String},
 auth: {type: String}
},
userAgent: {type: String}, // optional, just an additional tracking field
deviceId: {type: String} // just additional tracking fields

如果您正在使用关系型数据库,您可以将`keys`部分存储在单独的列中或使用`JSON`类型列。 要知道的主要内容是,`webpush.sendNotification(...)`采用具有以下接口的对象:
export interface PushSubscription {
    endpoint: string;
    keys: {
        p256dh: string;
        auth: string;
    };
}

基本上这表示您的数据库将需要跟踪订阅所需的这些属性。您可以选择添加 userId 和其他特定用例。


0

您可以将Web推送订阅存储为包含3个元素的JSON数组字符串:[endpoint,p256dh,auth]

您的表可能如下所示:

CREATE TABLE push_subscriptions(
  id BIGINT PRIMARY KEY AUTOINCREMENT,
  user_id BIGINT NOT NULL,
  user_agent VARCHAR(100),
  technology VARCHAR(10),
  subscription VARCHAR(255) UNIQUE,
  created_at TIMESTAMPZ
);

其中technology可能是:webpush,firebase,apn


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接