在 Rails 网络推送通知中识别用户

Identifying users in Rails Web push notifications

我正在开发一个 Rails 应用程序,我想在某些操作发生时向特定用户发送网络推送通知,例如:

用户开始跟踪计时器,但计时器已 运行 超过 6 小时。然后该应用会向该用户发送网络通知。

我一直在研究并发现 this tutorial,作者为 Rails 实现了推送通知,但是没有关于如何识别用户的见解。

据我了解,用户需要从他们的浏览器订阅才能获得推送通知,但是,考虑到每个用户都可以从多个浏览器使用该应用程序,我如何自动 subscribe/unsubscribe 一个用户对于他们使用的应用程序的所有浏览器中的通知?

该端点对于浏览器而言是唯一的,因此您需要在您的应用程序顶部使用额外的身份验证方案来将用户信息与新端点一起发送。

将端点存储在服务器上时,您需要将元数据(即用户 ID)附加到端点:

@subscription = Subscriptions.new endpoint: params[:endpoint]

@subscription.user = current_user
// or if you send with AJAX the user id together with the endpoint 
@subscription.user = User.find params[:user_id]

在第二种情况下,我建议签署用户 ID 或使用秘密令牌,否则任何人都可以像其他用户一样订阅推送通知。

然后您可以从数据库中删除属于该用户 ID 的所有端点以取消订阅他的所有设备。

但是我认为这不是一个好的做法:用户可能希望在一台设备上而不是另一台设备上接收通知。

所以,我所做的是将 notification_subscription 模型添加到我的 User 模型中。

在我的 javascript 上,我检查是否存在当前的浏览器订阅:

this.serviceWorkerReady()
  .then((serviceWorkerRegistration) => {
     serviceWorkerRegistration.pushManager.getSubscription()
     .then((pushSubscription) => {
        if (pushSubscription && _.includes(subscriptionEndpoints, pushSubscription.endpoint)) {
          return;
     }

     this.subscribe();
  });
});

我检查当前订阅是否已存在于用户存储的端点中,如果不存在则进行订阅。

在订阅时,我将新端点发送到后端,后端将新订阅添加到用户:

$.post(Routes.users_subscriptions_path({ format: 'json' }), {
  subscription: subscription.toJSON()
});

然后我可以向每个端点的用户发送通知:

def push_notifications_to_user(user)
    message = {
      title: "A message!",
      tag: 'notification-tag'
    }

    user.notification_subscriptions.each do |subscription|
      begin
        Webpush.payload_send(
          message: JSON.generate(message),
          endpoint: endpoint,
          p256dh: p256dh,
          auth: auth,
          api_key: public_key
        )
      rescue Webpush::InvalidSubscription => exception
        subscription.destroy
      end
    end
  end

如果端点无效,webpush gem 会引发 InvalidSubscription 异常,我们可以销毁该端点以仅保留用户的有效端点。