iOS 開發之新版 APNs 搭建必備知識

zhan71 7年前發布 | 19K 次閱讀 Apple 服務器 iOS開發 移動開發

一、設備token和消息的生命周期

關于設備token以及推送消息的生命周期需要注意下面幾點:

  • Token會在iOS系統更新或者設備數據、設置被擦除的時候改變。
  • 當設備離線的時候,APNS會將消息數據存儲一段時間,等設備上線后重發。如果設備在離線期間,向APNS發送了多條推送消息,APNS將會丟棄掉前面的一些消息,只保留后面的消息,要是設備長時間離線,則會將所有的消息丟棄掉。
  • 可以通過設置http/2頭中的 apns-collapse-id 鍵值對來合并消息,比如: apns-collapse-id : 2 ,那么value為2的消息將被APNS合并成一條消息推送給設備。

二、Provider(后臺)與APNs的交互

Provider(即,APP的后臺)與APNS有兩種安全的交互方式,都必須采用TLS以保證可靠性,更詳細的內容繼續往下看。

TLS 的簡單理解是,為了保證數據傳輸安全,在HTTP層與TCP層之間插入的一個安全校驗層,它所做的事情簡單來說就是: “通過CA申請的證書驗證client與server是可靠的之后,通過相應的公私鑰加密一個 協商的公鑰 ,之后的真實數據傳輸就使用這個公鑰進行加密,以保證數據的安全可靠性” ,關于TLS的更詳細的介紹

基于Token的方式(Token-Based Provider-to-APNs Trust)

1、流程概述

這種方式適合在基于HTTP/2協議的Provider使用,它與APNs之間的連接通過 JWT(JSON web tokens) 來驗證。在這種方式下不需要使用證書+私鑰的方式來建立可靠連接。Provider只需要提供一對公私鑰(私鑰給APNs保存,公鑰Provider自己保存),并使用其中的私鑰生成并加密JWT Token,每次向APNs請求推送的時候帶上這個Token即可。

具體步驟如下:

  1. Provider通過 TLS 向APNs發起請求。
  2. APNs返回一個證書給Provider。
  3. Provier驗證這個證書。通過后,發送push數據并帶上JWT token。
  4. APNs驗證token,并返回請求的結果。

Establishing and using token-based connection trust between a provider and APNs

建立TLS連接必須要有一個 GeoTrust Global CA root certificate ,在macOS中,這個證書已經安裝在keychain中,如果是其他操作系統則可以在 GeoTrust Root Certificates website 下載。

2、Provider Authentication Tokens

關于JWT(JSON Web Token)的詳細資料可以通過 這里 了解。同時也可以從 這里 找到一些現成可用的庫。

下面對JWT進行詳細的介紹,一個JWT實際上是一個JSON對象,它的頭部必須包含:

  • 用以加密token的加密算法( alg ) ,比如:ES256。
  • 10個字符長度的標識符( kid ),(登入蘋果開發者賬號后,進入到 Certificates, Identifiers & Profiles ,然后點擊 APNs Auth Key ,最后在右側找到 Apple Push Notification Authentication Key (Sandbox & Production) 選項,點擊創建后可以創建一個p8文件。)

同時他的claims payload部分必須包含:

  • issuer( iss ) registered claim key,其值就是10個字符長的Team ID。
  • issued at ( iat ) registered claim key,其值是一個秒級的UTC時間戳。

比如:

{
    "alg": "ES256",
    "kid": "ABC123DEFG"
}
{
    "iss": "DEF123GHIJ",
    "iat": 1437179036
 }

創建完這個token后,必須使用自己的私鑰對其進行加密,然后再采用基于P-256曲線和SHA-256哈希算法的橢圓曲線數字簽名算法(ECDSA)進行簽名,并將 alg 鍵的值設置為 ES256 。(注意:APNs只支持 ES256 簽名的JWT,否則會返回 InvalidProviderToken(403) 錯誤)

為了保證安全,APNs要求定期更新token,時間間隔為1小時,如果APNs發現當前的時間戳與 iat 值中的時間戳相比,大于一個小時,那么APNs會拒絕推送消息,并返回 ExpiredProviderToken (403) 錯誤。

基于證書的方式(Certificate-based connection trust)

流程概述

這種方式是指Provider可以采用一個唯一的證書以及一個加密的私鑰來與APNs交互,其中證書是由蘋果產生的(通過蘋果賬號登錄到 developer account 配置創建)。整個交互過程如下:

  1. Provider通過 TLS 向APNs請求連接。
  2. APNs向Provider返回一個APNs證書。
  3. Provider驗證這個APNs證書,并將從蘋果官網獲取的證書返回給APNs。
  4. APNs驗證通過后,這個鏈接就算是建立了。

Establishing certificate-based connection trust between a provider and APNs

APNs Provider Certificates

創建步驟可以參考 Configure push notifications 中的Generate a universal APNs client SSL certificate章節。

三、APNs連接

連接的管理

蘋果的兩個APNs server分別為:

  • Development server: api.development.push.apple.com:443
  • Production server: api.push.apple.com:443

要與APNs交互要求server必須支持1.2及上版本的TLS協議。通過上面的介紹我們已經知道,server跟APNs交互有兩種方式:基于JWT的方式以及基于證書的方式。為了保證高質量的使用APNs應該注意如下幾點:

  • 對于基于JWT的方式,應該定時更新token,token的有效期為1小時。
  • 對于基于JWT的方式,能每次請求都創建新的token,盡量在一小時內使用同一個token。
  • 不能頻繁的建立、關閉連接,否則APNs會把這當做是黑客攻擊,拒絕訪問。應該盡量將連接保活,直到你認為這個連接接下來會長時間不使用為止。
  • 當需要發送大量的推送數據的時候,可以同時創建多個連接,以改善性能。
  • 當吊銷證書或者token時,應該關閉所有相關的連接。

HTTP/2的請求與響應

詳情可參見蘋果官方文檔 HTTP/2 Request to APNs 。這里介紹了接口的 請求參數返回結果錯誤碼 以及 示例代碼 。下面僅截取了其中的例子,以加深對APNs的使用的理解:

  • 基于證書的方式的request:

    HEADERS

    - END_STREAM
    + END_HEADERS
    :method = POST
    :scheme = https
    :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
    host = api.development.push.apple.com
    apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b //可以不填,如果不填APNs會自己創建一個UUID并在response中返回
    apns-expiration = 0
    apns-priority = 10
    

    DATA

    + END_STREAM
      { "aps" : { "alert" : "Hello" } }</code></pre> </li> 
    

  • 基于token方式的request:

    HEADERS

    - END_STREAM
    + END_HEADERS
    :method = POST
    :scheme = https
    :path = /3/device/00fc13adff785122b4ad28809a3420982341241421348097878e577c991de8f0
    host = api.development.push.apple.com
    authorization = bearer eyAia2lkIjogIjhZTDNHM1JSWDciIH0.eyAiaXNzIjogIkM4Nk5WOUpYM0QiLCAiaWF0I
    

    jogIjE0NTkxNDM1ODA2NTAiIH0.MEYCIQDzqyahmH1rz1s-LFNkylXEa2lZ_aOCX4daxxTZkVEGzwIhALvkClnx5m5eAT6 Lxw7LZtEQcH6JENhJTMArwLf3sXwi apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b apns-expiration = 0 apns-priority = 10 apns-topic = <MyAppTopic> DATA

    + END_STREAM
      { "aps" : { "alert" : "Hello" } }</code></pre> </li> 
    

  • 失敗后的response:

    HEADERS

    - END_STREAM
    + END_HEADERS
    :status = 400
    content-type = application/json
      apns-id: <a_UUID>
    

    DATA

    + END_STREAM
    { "reason" : "BadDeviceToken" }</code></pre> </li> 
    

  • 成功后的response:

    HEADERS

    - END_STREAM
    + END_HEADERS
      apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
      :status = 200</code></pre> </li> 
    

    </ul>

    四、設備token的生成與分發

    在app啟動的時候,必須向iOS系統注冊遠程推送,成功后,蘋果將會返回一個設備token給app,此時app就可以將這個token上報給自己的后臺。

    如果有必要產生一個新的token,APNs會使用設備證書生成一個token(其中包含了一個設備ID),并使用token key加密后返回給設備。同時設備會將這個token以 NSData 對象的形式返回給app,app獲取到該token之后應該將其發送到自己后臺,后臺之后就可以通過這個token來發送推送數據。過程如下圖:

    Managing the device token

    最后

    通過蘋果的官方文檔我們可以知道provider與APNs的交互過程中,需要注意一下幾點:

    • 推薦使用 HTTP/2 協議。
    • 必須加入 TLS 層。
    • 基于JWT的方式,token的最大有效期為1小時,并且不能頻繁更換token。
    • 不能頻繁創建、關閉連接,應該盡量少開連接,如果過于頻繁,APNs將把其當做是黑客攻擊,但是如果數據量大,可以同時多個連接向APNs發送消息。
    • 吊銷token或者證書的時候,應該及時關閉老的連接。

    參考文獻

    1. APNs Overview
    2. Communicating with APNs

     

    來自:http://www.jianshu.com/p/d8dba6c2c07a

     

 本文由用戶 zhan71 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!