Skip to content
Anonymous

Web Push Notifications 全解析:從 VAPID 金鑰到動態提醒實戰

如何在 DueWise 中實作高效的 Web Push 通知?這篇文章涵蓋了 VAPID 金鑰、訂閱處理以及利用 Cloudflare Worker 觸發提醒的完整流程。

#Web Push #Notifications #VAPID #Cloudflare Workers

Web Push Notifications 全解析:從 VAPID 金鑰到動態提醒實戰

對於一個「效期管理」應用程式來說,如果沒有主動通知提醒,其功用就減半了。由於 DueWise 是一個 PWA,我們無法使用原生 App 的 APNs 或 FCM 系統。我們必須仰賴 Web Push API

實作 Web Push 聽起來很簡單,但實際上涉及到多個層面的安全與加密 (VAPID)。這篇文章將完整拆解 DueWise 的推播技術架構。

什麼是 VAPID?為什麼需要它?

VAPID (Voluntary Application Server Identification) 是 Web 推播協議中的一個重要部分。它是一對「非對稱金鑰」 (Public/Private Key),其作用有二:

  1. 驗證伺服器身份: 確保推播訊息真的是由你的伺服器發出的,而不是冒名頂替。
  2. 避免垃圾訊息: 推播網關(如 Google 的 FCM 網關)利用 VAPID 來追蹤發送者,防止惡意攻擊。

在 DueWise 中,我們將這些金鑰安全地儲存於 Cloudflare 的環境變數中,絕不暴露於前端。

第一階段:瀏覽器端的「授權與訂閱」

用戶必須先「同意」接收通知。我們在 src/pages/api/push/subscribe.ts 相關邏輯中處理了這個流程。

1. 取得訂閱對象 (Subscription Object)

當用戶點擊「開啟提醒」時,瀏覽器會向推播網關產出一個唯一的端點 (Endpoint) 以及一組加密金鑰 (p256dh, auth)。

const registration = await navigator.serviceWorker.ready;
const subscription = await registration.pushManager.subscribe({
  userVisibleOnly: true,
  applicationServerKey: urlBase64ToUint8Array(VAPID_PUBLIC_KEY)
});

2. 存儲訂閱資訊

這一步至關重要。我們必須將這個 subscription JSON 物件傳回後端,並關聯至用戶的電子郵件,存入 Cloudflare D1 資料庫

第二階段:伺服器端的「訊息觸發」

發送通知的過程實際上是一個加密過的 HTTP POST 請求。在 DueWise 的構架中,我們利用 GitHub Actions 執行 Daily Push 任務,這會觸發一個特定的 API。

1. 加密訊息內容 (Payload)

為了保護隱私,推播內容必須在伺服器端加密。我們使用了 @pushforge/builder 等工具庫來封裝這層複雜的加密運算。

2. 處理過期的端點

推播網關可能會隨時將某些訂閱標記為「無效」(例如用戶在設定中關閉了瀏覽器通知權限)。當發送請求返回 404 或 410 錯誤時,我們的 API 會自動從資料庫中移除該失效的訂閱資訊,保持系統的高效。

第三階段:Service Worker 的「訊息接收」

當訊息抵達用戶設備時,Service Worker 接管了這一切。即使瀏覽器標籤頁已關閉,Service Worker 依然能喚醒。

self.addEventListener('push', (event) => {
  const data = event.data.json();
  const options = {
    body: data.body,
    icon: '/icons/icon-192x192.png',
    badge: '/icons/badge-96x96.png',
    data: { url: '/app' } // 點擊通知後的導向路徑
  };
  event.waitUntil(
    self.registration.showNotification(data.title, options)
  );
});

技術挑戰:iOS PWA 的特殊處理

在 iOS 上實作推播有一個著名的限制:用戶必須先將 PWA 「新增至主螢幕」 後,瀏覽器才會允許啟動 Push API。此外,Apple 要求這個動作必須是由「用戶手動觸發」的。

為此,DueWise 設計了引導式的 UI。當系統偵測到是 iOS 環境且未安裝 PWA 時,我們會跳出一個溫馨的導引視窗,告訴用戶如何完成安裝並啟用。

安全性警告:PUSH_TRIGGER_SECRET

為了防止駭客惡意觸發大量的推播請求導致我們的伺服器成本上升或發信信譽受損,我們實作了一個名為 PUSH_TRIGGER_SECRET 的門神金鑰。任何發送推播的 API 請求都必須在 Header 中帶上這組正確的金鑰,否則一律拒絕處理。

結論

Web Push 讓 PWA 擁有了靈魂——即時性。透過 VAPID 的嚴密加密、D1 資料庫的訂閱鏈結,以及 Service Worker 的無息背景執行,DueWise 成功地將傳統的 Web 工具轉變為一個隨時守護用戶物品效期的智慧管家。

下一篇文章,我們將深入資料庫底層:「Cloudflare D1:如何在邊緣環境實作高度可靠的 SQLite 存儲方案」。