Just My Life & My Work

最近需要整合中國可比較順利收到遠端推播的平台極光,我們決定使用最新的 Apple 推播通知(APNs)認證機制。

先前已有在文章:Apple 推播通知服務憑證更新研究過,了解舊的 p12 憑證與新的 p8 金鑰之差異,有更好的方法就與時俱進吧!

.

1. .p12 憑證

  • 舊機制:以前要使用 APNs,必須在 Apple Developer 產生「推播憑證(Push Certificate)」,然後把它匯出成 .p12 檔案(包含憑證與私鑰)。
  • 綁定性高:這個 .p12 是針對「單一 App」產生的,每個 App 要推播就得有自己的憑證。
  • 管理麻煩:如果有很多 App,要管理很多 .p12,到期還得逐一更新。

2. .p8 金鑰

  • 新機制 (2016 後):Apple 推出了「APNs Auth Key」機制,用 .p8 私鑰檔案來取代傳統憑證。
  • 好處
    • 一把 .p8 金鑰可以同時支援多個 App,不需要為每個 App 建立不同檔案。
    • 不會每年過期,只要不撤銷,金鑰就一直有效。
    • 伺服器端使用 JWT(JSON Web Token)來跟 APNs 做身份驗證,安全性更好。
  • 限制:一個 Apple 開發者帳號最多能建立 2 組 APNs .p8 金鑰。

小結

  • .p12 → 舊式、以「App」為單位的憑證,會過期,需要管理多份。
  • .p8 → 新式、以「帳號」為單位的金鑰,不會過期,維護更簡單。
特性.p12 憑證.p8 金鑰
用途舊式 APNs 推播憑證新式 APNs Auth Key
綁定範圍一個 App 一個憑證一個金鑰可支援同帳號下多個 App
檔案內容包含憑證 + 私鑰單純私鑰檔
有效期限1 年,需要更新無期限(除非手動撤銷)
建立數量每個 App 都要建立每個帳號最多可有 2 把
伺服器驗證方式憑證驗證 (TLS)JWT (JSON Web Token)
管理難度較高:多 App 多憑證,會過期較低:一把金鑰即可搞定
Apple 推薦度已是舊方案官方推薦的新方案

🔑 為什麼 .p12 要分「開發」和「生產」

  • .p12 憑證是 舊式基於 TLS 的驗證
  • Apple 當年設計 APNs 時,把 Sandbox(測試環境)Production(正式環境) 分成兩個不同的伺服器:
    • 開發:api.sandbox.push.apple.com
    • 生產:api.push.apple.com
  • 所以 Apple 就要求分別申請「iOS Development」和「iOS Production」推播憑證,伺服器端要針對不同環境載入不同的 .p12

結果:一個 App 常常會有 兩個憑證(開發、上線),要分別維護。


🔑 為什麼 .p8 不用區分

  • .p8 是新的 JWT 驗證機制
  • 使用 .p8 時,伺服器會帶著一個 Token(包含 Team ID、Key ID、App 的 Bundle ID),去跟 Apple 要憑證。
  • Apple 後端會自己判斷這個推播要送到 Sandbox 還是 Production,不需要準備兩份檔案。
  • 只需要在發送請求時指定環境(或讓 Apple 自動判斷),同一把金鑰就能處理兩邊。

結果:.p8 大幅簡化流程 → 一個檔案,全環境通用


📌 總結

  • .p12:舊式 → TLS 驗證 → 必須分「開發」和「生產」憑證。
  • .p8:新式 → JWT 驗證 → 一把金鑰支援全部環境。

🟦 .p12 推播驗證流程(舊式,TLS 憑證)

[App] ---> (APNs Token) ---> [Server]
                                   |
                     [Server 使用 p12 憑證]
                                   |
      開發? ---------------------> APNs Sandbox (api.sandbox.push.apple.com)
      生產? ---------------------> APNs Production (api.push.apple.com)

👉 必須有 兩份憑證(開發 / 生產),伺服器端要分別配置。


🟩 .p8 推播驗證流程(新式,JWT 金鑰)

[App] ---> (APNs Token) ---> [Server]
                                   |
                     [Server 使用 p8 金鑰產生 JWT]
                                   |
                            [同一個 APNs 入口]
                            api.push.apple.com
                                   |
                   Apple 伺服器自動判斷 (Sandbox / Production)

👉 一把 .p8 金鑰 就能支援 所有環境,不用額外區分。


📌 小總結

  • .p12:要幫伺服器「挑對環境」+「用對憑證」。
  • .p8:只要用 JWT 帶金鑰,剩下的交給 Apple 幫決定。

公司為了區分環境(Dev / UAT / PT / Prod)會建立 不同的 Bundle Identifier。這樣每個環境都是獨立 App,對應不同的 Provisioning Profile & 推播設定。

來幫拆解一下在 .p12.p8 兩種世界下會怎麼處理:


🔑 .p12 的情況

  • 每個 Bundle ID 都要在 Apple Developer 後台啟用 Push Notifications。
  • 啟用後,每個環境(App ID)都要各自申請憑證:
    • io.dev.DigitalCurrency → Development p12 + Production p12
    • io.uat.DigitalCurrency → Development p12 + Production p12
    • io.pt.DigitalCurrency → Development p12 + Production p12
    • io.prod.DigitalCurrency → Development p12 + Production p12
  • 所以最多會產生 8 個 .p12 檔案(4 個 App × 2 個環境)。
  • 伺服器端要知道:這次推播是送給哪個 App,再載入對應的 .p12
    👉 缺點:檔案一堆,管理很痛苦。

🔑 .p8 的情況

  • 在 Apple Developer 產生 一把 APNs Auth Key (.p8)
  • 這把金鑰可以授權整個 Team 下的所有 App(只要這些 App 都啟用了推播)。
  • 推播時,伺服器會帶入:
    • Team ID
    • Key ID
    • App 的 Bundle ID(這裡就能區分 Dev / UAT / PT / Prod)
  • Apple 就會幫把推播送到正確的 App & 環境。
    👉 優點:只要 一把 .p8,不用為 4 個環境分開處理。

📌 小總結

  • .p12 → 4 個環境 × 2 個憑證類型 = 最多 8 個檔案。
  • .p8 → 一把金鑰搞定全部環境(只要帶對 Bundle ID)。

📊 .p12 vs .p8 在多環境 App 下的差異

特性.p12 憑證 (舊式).p8 金鑰 (新式)
檔案數量每個 Bundle ID 需要各自憑證,且分開發/生產 → 4 環境 × 2 = 最多 8 個 .p12一把 .p8 即可,支援所有 Bundle ID
環境區分伺服器要知道要連 Sandbox 還是 Production,並載入對應的憑證在 JWT 中指定 Bundle ID,Apple 伺服器自動判斷環境
維護成本多檔案管理,憑證 1 年到期要更新(每個環境都要)單一檔案,不會過期(除非手動撤銷)
App 擴充性新增一個環境(新 Bundle ID)= 要重新產生憑證新增一個環境(新 Bundle ID)= 直接用同一把 .p8
伺服器端程式碼需要針對不同環境切換憑證檔使用一個金鑰,只需切換 JWT 內的 bundle-id
Apple 推薦度已算是 legacy,官方建議轉移官方推薦方案

👉 結論:

  • .p12:管理多環境超麻煩(8 個檔案還會過期)。
  • .p8:一把金鑰搞定全部 Bundle ID,長遠來看維護最省心。

伺服器端送推播,畫個直觀的「程式切換不同 Bundle ID 邏輯圖」:


🟦 .p12 憑證(舊式)

        [伺服器程式邏輯]
                 |
   判斷要推播的環境是哪一個?
   ┌───────────────┬───────────────┬───────────────┬───────────────┐
   |               |               |               |               |
[Dev]           [UAT]            [PT]            [Prod]
   |               |               |               |
 載入對應的 .p12   載入對應的 .p12   載入對應的 .p12   載入對應的 .p12
 (Dev or Prod)    (Dev or Prod)    (Dev or Prod)    (Dev or Prod)
   |               |               |               |
   v               v               v               v
 [APNs Sandbox]  [APNs Sandbox]  [APNs Sandbox]  [APNs Production]
 [APNs Prod]     [APNs Prod]     [APNs Prod]     [APNs Production]

👉 結果:每個環境要對應不同檔案,還要判斷 sandbox / production,管理超級繁瑣。


🟩 .p8 金鑰(新式)

        [伺服器程式邏輯]
                 |
   判斷要推播的環境是哪一個?
   ┌───────────────┬───────────────┬───────────────┬───────────────┐
   |               |               |               |               |
[Dev]           [UAT]            [PT]            [Prod]
   |               |               |               |
 note.topic =     note.topic =     note.topic =    note.topic =
 "io.dev..."      "io.uat..."      "io.pt..."      "io.prod..."
   |               |               |               |
   v               v               v               v
            [同一把 .p8 金鑰]
                 |
          [Apple APNs Server]
                 |
   Apple 自動判斷要送 Sandbox 或 Production

👉 結果:只要一把 .p8,程式裡只要換 Bundle ID,Apple 就幫決定推送到哪個環境。


📌 小總結

  • .p12檔案爆炸(每環境 × 2),程式要判斷很多東西。
  • .p8一把金鑰就搞定,程式邏輯單純到只剩下 note.topic = <Bundle ID>

.p8 為開發者帶來更多的便利性,未來若沒有其他考量,肯定要選擇 .p8 來進行遠端推播整合。🤠

隨意留個言吧:)~

這個網站採用 Akismet 服務減少垃圾留言。進一步了解 Akismet 如何處理網站訪客的留言資料

標籤雲