了解如何存储 Web 推送端点

Understanding How to Store Web Push Endpoints

我正在尝试开始在我的一个应用程序中实施 Web Push。在我发现的示例中,客户端的端点 URL 通常存储在内存中,并带有一条评论,如:

In production you would store this in your database...

因为只有我的应用程序 can/will 的注册用户才能收到推送通知,我的计划是将端点 URL 存储在我数据库中用户的元数据中。到目前为止,还不错。

当我想允许同一个用户在多个设备上接收通知时,问题就来了。理论上,我将为用户订阅的每个设备向数据库添加一个新端点。然而,在测试中,我注意到端点随 同一设备 上的每个 subscription/unsubscription 而变化。因此,如果一个用户 subscribes/unsubscribes 在同一台设备上连续多次,我最终会为该用户保存多个端点(除其中一个外,其他端点都不好)。

what I have read 开始,当用户取消订阅或端点失效时,没有可靠的方法来通知。那么,如何判断在添加新端点之前是否应该删除旧端点?

如何阻止用户通过重复 subscription/unsubscription 向我的数据库中填充端点来有效地发动拒绝服务攻击?

这更像是个玩笑(我显然可以限制给定用户的总端点),但我看到的问题是,当需要发送通知时,我会用数百个通知来发送通知服务对于无效端点。


我希望我的服务器上的订阅逻辑是:

  1. 检查我们是否已经为此 user/device 组合保存了端点
  2. 如果没有添加,如果有,更新

问题是我不知道如何可靠地执行 #1。

I will just add a new endpoint to the database for each device the user subscribes with

最好的方法是 table 像这样:

endpoint | user_id
  • endpoint 上添加唯一约束(或主键):您不想将同一个浏览器关联到多个用户,因为它是一团糟(如果端点已经存在但它有一个不同的 user_id,只需更新与之关联的 user_id
  • user_id 是指向您的用户的外键 table

if a user subscribes/unsubscribes several times in a row on the same device, I wind up with several endpoints saved for that user (all but one of which are bad).

是的,不幸的是推送API有a wild unsubscription mechanism,你必须处理它。

端点可能会过期或无效(甚至是恶意的,如 android.chromlum.info)。当您尝试从您的应用程序服务器发送推送消息时,您需要检测故障(使用 HTTP 状态代码、超时等)。然后,对于某种故障(永久性故障,如过期),您需要删除端点。

What's to stop a user from effectively mounting a denial of service attack by filling my db with endpoints through repeated subscription/unsubscription?

如上所述,您需要正确删除无效端点,一旦您意识到它们已过期或无效。基本上他们最多会产生一个无效请求。此外,如果您的吞吐量很高,您的服务器只需几秒钟就可以向数千个端点发出请求。

我的建议是基于我在开发时所做的大量实验和思考 Pushpad