推送通知概览

简要介绍什么是推送通知、为什么要使用推送通知以及推送通知的工作原理。

Matt Gaunt

什么是推送通知?

借助推送消息,您可以让用户即使在未使用您的网站时也能注意到相关信息。之所以称为推送消息,是因为您可以向用户“推送”信息,即使用户处于非活跃状态也是如此。比较推送技术拉取技术,进一步了解此概念。

通知会向用户显示少量信息。网站可以使用通知告知用户重要且紧急的事件,或用户需要执行的操作。通知的外观和风格因平台而异:

macOS 和 Android 上的通知示例。
macOS 和 Android 上的通知示例。

推送消息和通知是两种不同的但互为补充的技术。 推送是一种技术,可让您从服务器向用户发送消息,即使用户未主动使用您的网站也是如此。通知是一种在用户设备上显示推送信息的技术。您可以在不使用推送消息的情况下使用通知。将来,您或许还可以使用不向用户显示通知的推送消息(静默推送),但浏览器目前不允许这样做。在实际使用中,它们通常一起使用。 非技术用户可能不了解推送消息和通知之间的区别。在本集合中,当我们说“推送通知”时,是指推送消息后将其显示为通知的组合。当我们所说的“推送消息”本身是指推送技术本身。当我们说“通知”时,是指通知技术本身。

为何使用推送通知?

  • 对于用户而言,推送通知是一种接收及时相关准确信息的方式。
  • 对于网站所有者来说,推送通知是提高用户互动度的一种方式。

推送通知的运作方式

概括来讲,实现推送通知的关键步骤如下:

  1. 添加客户端逻辑以向用户请求发送推送通知的权限,然后将客户端标识符信息发送到您的服务器以存储在数据库中。
  2. 添加服务器逻辑以将消息推送到客户端设备。
  3. 添加客户端逻辑,以接收已推送到设备的消息并将其显示为通知。

本页面的其余部分将更详细地介绍这些步骤。

获取发送推送通知的权限

首先,您的网站需要征得用户的许可才能发送推送通知。此操作应由用户手势触发,例如点击 Do you want to receive push notifications? 提示旁边的 Yes 按钮。确认后,调用 Notification.requestPermission()。用户设备上的操作系统或浏览器可能会显示某种界面,以正式确认用户想要选择接收推送通知。此界面因平台而异。

为客户端订阅推送通知

获得权限后,您的网站需要发起用户订阅推送通知的流程。这通过 JavaScript 使用 Push API 完成。您需要在订阅过程中提供一个公共身份验证密钥,稍后会详细介绍。您启动订阅流程后,浏览器会向一项名为推送服务的 Web 服务发出网络请求,您稍后还会详细了解这项服务。

假设订阅成功,浏览器会返回 PushSubscription 对象。您需要长期存储这些数据。这通常是通过将信息发送到您控制的服务器,然后将信息存储在数据库中来实现的。

获取发送推送消息的权限。获取 PushSubscription。将 PushSubscription 发送到您的服务器。

发送推送消息

您的服务器实际上不会直接向客户端发送推送消息。推送服务可以做到这一点。推送服务是由用户的浏览器供应商控制的 Web 服务。如果要向客户端发送推送通知,您需要向推送服务发出网络服务请求。您发送给推送服务的 Web 服务请求称为 Web 推送协议请求。Web 推送协议请求应包含:

  • 要包含在消息中的数据。
  • 要将消息发送到的客户端。
  • 有关推送服务应如何传送消息的说明。例如,您可以指定推送服务应在 10 分钟后停止尝试发送消息。

通常,您会通过自己控制的服务器发出 Web 推送协议请求。当然,您的服务器不必自行构建原始 Web 服务请求。有些库可以为您处理此问题,例如 web-push-libs。但底层机制是通过 HTTP 发出的 Web 服务请求。

您的服务器向推送服务发送 Web 推送协议请求,然后推送服务将消息发送到用户的设备。

推送服务会接收您的请求、对其进行身份验证,并将推送消息路由到相应的客户端。如果客户端的浏览器处于离线状态,推送服务会将推送消息加入队列,直到浏览器恢复在线状态。

每个浏览器都可以使用它想要的任何推送服务。作为网站开发者,您无法控制这一点。这不是问题,因为 Web Push 协议请求是标准化的。换句话说,您无需关心浏览器供应商使用的是哪种推送服务。您只需确保您的 Web 推送协议请求符合规范即可。除此之外,规范还规定请求必须包含特定标头,并且数据必须以字节流的形式发送。

不过,您需要确保将 Web 推送协议请求发送到正确的推送服务。浏览器在订阅过程中返回给您的 PushSubscription 数据提供了这些信息。PushSubscription 对象如下所示:

{
  "endpoint": "https://fcm.googleapis.com/fcm/send/c1KrmpTuRm…",
  "expirationTime": null,
  "keys": {
    "p256dh": "BGyyVt9FFV…",
    "auth": "R9sidzkcdf…"
  }
}

endpoint 的网域本质上是推送服务。endpoint 的路径是客户端标识符信息,可帮助推送服务准确确定要将消息推送到哪个客户端。

keys 用于加密,详见下文。

加密推送消息

您发送到推送服务的数据必须经过加密。这样可以防止推送服务查看您发送给客户端的数据。请注意,浏览器供应商决定使用哪种推送服务,而推送服务在理论上可能不安全。您的服务器必须使用 PushSubscription 中提供的 keys 对其 Web 推送协议请求进行加密。

对 Web 推送协议请求进行签名

推送服务提供了一种方法,可防止任何其他人向您的用户发送消息。从技术上讲,您不必这样做,但最简单的 Chrome 实现方式却需要这样做。在 Firefox 中,此设置是可选的。其他浏览器未来可能也需要此属性。

此工作流涉及应用专有的私钥和公钥。身份验证过程大致如下:

  • 生成私钥和公钥是一次性任务。私钥和公钥的组合称为应用服务器密钥。您可能还会看到它们被称为 VAPID 密钥VAPID 是定义此身份验证流程的规范。
  • 通过 JavaScript 代码将客户端订阅推送通知时,您需要提供公钥。当推送服务为设备生成 endpoint 时,它会将提供的公钥与 endpoint 相关联。
  • 发送 Web 推送协议请求时,您需要使用私钥对一些 JSON 信息进行签名。
  • 当推送服务收到您的 Web 推送协议请求时,它会使用存储的公钥对已签名的信息进行身份验证。如果签名有效,则推送服务会知道请求来自具有匹配私钥的服务器。

自定义推送消息的传送

Web 推送协议请求规范还定义了一些参数,可让您自定义推送服务尝试向客户端发送推送消息的方式。例如,您可以自定义:

  • 消息的存活时间 (TTL),用于指定推送服务应尝试传送消息的时长。
  • 消息的紧急程度。如果推送服务仅传送高优先级消息以延长客户端的电池续航时间,则此属性非常有用。
  • 消息的主题,系统会将同一主题的所有待处理消息替换为最新消息。

接收并以通知的形式显示推送的消息

将 Web 推送协议请求发送到推送服务后,推送服务会将您的请求保持在队列中,直到发生以下任一事件:

  1. 客户端上线,推送服务传送推送消息。
  2. 消息过期。

当客户端浏览器收到推送消息时,它会解密推送消息数据,并将 push 事件分派给您的服务工作器。Service Worker 基本上就是可以在后台运行的 JavaScript 代码,即使您的网站未打开或浏览器已关闭也是如此。在 Service Worker 的 push 事件处理程序中,您可以调用 ServiceWorkerRegistration.showNotification() 以将信息显示为通知。

消息到达设备。浏览器唤醒 Service Worker。系统会分派推送事件。

下一步做什么

Codelab