最近需要整合中國可比較順利收到遠端推播的平台極光,我們決定使用最新的 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 p12io.uat.DigitalCurrency→ Development p12 + Production p12io.pt.DigitalCurrency→ Development p12 + Production p12io.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 來進行遠端推播整合。🤠

隨意留個言吧:)~