版本記錄
| 版本號 | 時間 |
|---|---|
| V1.0 | 2018.07.14 |
前言
我們做APP很多時候都需要推送功能,以直播為例,如果你關(guān)注的主播開播了,那么就需要向關(guān)注這個主播的人發(fā)送開播通知,提醒用戶去看播,這個只是一個小的方面,具體應(yīng)用根據(jù)公司的業(yè)務(wù)邏輯而定。前面已經(jīng)花了很多篇幅介紹了極光推送,其實極光推送無非就是將我們客戶端和服務(wù)端做的很多東西封裝了一下,節(jié)省了我們很多處理邏輯和流程,這一篇開始,我們就利用系統(tǒng)的原生推送類結(jié)合工程實踐說一下系統(tǒng)推送的集成,希望我的講解能讓大家很清楚的理解它。感興趣的可以看上面幾篇。
1. 系統(tǒng)推送的集成(一) —— 基本集成流程(一)
2. 系統(tǒng)推送的集成(二) —— 推送遇到的幾個坑之BadDeviceToken問題(一)
3. 系統(tǒng)推送的集成(三) —— 本地和遠程通知編程指南之你的App的通知 - 本地和遠程通知概覽(一)
4. 系統(tǒng)推送的集成(四) —— 本地和遠程通知編程指南之你的App的通知 - 管理您的應(yīng)用程序的通知支持(二)
5. 系統(tǒng)推送的集成(五) —— 本地和遠程通知編程指南之你的App的通知 - 調(diào)度和處理本地通知(三)
6. 系統(tǒng)推送的集成(六) —— 本地和遠程通知編程指南之你的App的通知 - 配置遠程通知支持(四)
7. 系統(tǒng)推送的集成(七) —— 本地和遠程通知編程指南之你的App的通知 - 修改和顯示通知(五)
8. 系統(tǒng)推送的集成(八) —— 本地和遠程通知編程指南之蘋果推送通知服務(wù)APNs - APNs概覽(一)
9. 系統(tǒng)推送的集成(九) —— 本地和遠程通知編程指南之蘋果推送通知服務(wù)APNs - 創(chuàng)建遠程通知Payload(二)
Communicating with APNs - 與APNs通信
APNs providerAPI允許您向APNs發(fā)送遠程通知請求。 然后,APNs會在iOS,tvOS和macOS設(shè)備上向您的應(yīng)用程序發(fā)送通知,并通過iOS向Apple Watch發(fā)送通知。
providerAPI基于HTTP / 2網(wǎng)絡(luò)協(xié)議。 每個交互都從您的provider的POST請求開始,該請求包含JSON的payload和device token。 APNs將通知payload轉(zhuǎn)發(fā)到由請求包含的設(shè)備令牌標識的特定用戶設(shè)備上的應(yīng)用程序。
provider是您配置為使用APNs的部署和管理的服務(wù)器。
Provider Authentication Tokens - provider認證令牌
要安全地連接到APNs,您可以使用provider身份驗證token或provider證書。本節(jié)介紹使用token的連接。
provider API支持JSON Web Token(JWT)規(guī)范,允許您將語句和元數(shù)據(jù)(稱為claims)傳遞給APNs,以及每個推送通知。有關(guān)詳細信息,請參閱https://tools.ietf.org/html/rfc7519上的規(guī)范。有關(guān)JWT的其他信息,以及用于生成簽名JWT的可用庫列表,請參閱https://jwt.io。
provider身份驗證token是您構(gòu)造的JSON對象,其標頭必須包含:
- 用于加密令牌的加密算法
(alg) - 從your developer account獲取的10個字符的key標識符
(kid)密鑰
token的聲明payload必須包括:
- 發(fā)布人
(iss)注冊的claim密鑰,其值為您的10個字符的團隊ID,從your developer account獲得。 - 已發(fā)布
(iat)注冊的claim密鑰,其值表示生成token的時間,以自Epoch以來的秒數(shù)(UTC)表示。
創(chuàng)建token后,您必須使用私鑰對其進行簽名。然后,您必須使用帶有P-256曲線和SHA-256哈希算法的Elliptic Curve Digital Signature Algorithm (ECDSA)加密token。在算法header鍵(alg)中指定值ES256。有關(guān)如何配置token的信息,請參閱Xcode幫助中的Configure push notifications。
APNs的解碼JWT provider身份驗證token具有以下格式:
{
"alg": "ES256",
"kid": "ABC123DEFG"
}
{
"iss": "DEF123GHIJ",
"iat": 1437179036
}
注意:APNs僅支持使用
ES256算法簽名的provider身份驗證token。 不安全的JWT或使用其他算法簽名的JWT將被拒絕,您的提供程序?qū)⑹盏?code>InvalidProviderToken(403)響應(yīng)。
為了確保安全性,APNs需要定期生成token。 新token具有在claim密鑰處發(fā)布的更新,其值指示token生成的時間。 如果token問題的時間戳不在最后一小時內(nèi),則APNs拒絕后續(xù)推送消息,返回ExpiredProviderToken(403)錯誤。
如果您懷疑provider token簽名密鑰已泄露,您可以從 your developer account撤消該密鑰。 您可以發(fā)出新的密鑰對,然后可以使用新的私鑰生成新的密鑰。 為了最大限度地提高安全性,請關(guān)閉所有使用已使用且已撤銷密鑰簽名的令牌的APNs的連接,并在使用使用新密鑰簽名的令牌之前重新連接。
APNs Provider Certificates - APNs Provider證書
您按照Xcode幫助中的Configure push notifications中的說明獲得的APNs provider證書可以連接到APNs的生產(chǎn)和開發(fā)Production and Development環(huán)境。
您可以使用您的APNs證書向您的主應(yīng)用程序發(fā)送通知,如其bundle ID,以及與該應(yīng)用程序關(guān)聯(lián)的任何Apple Watch復(fù)雜功能或后備VoIP服務(wù)。 使用證書中的(1.2.840.113635.100.6.3.6)擴展名來標識推送通知的主題。 例如,如果您為應(yīng)用程序提供了包ID com.yourcompany.yourexampleapp,則可以在證書中指定以下主題:
Extension ( 1.2.840.113635.100.6.3.6 )
Critical NO
Data com.yourcompany.yourexampleapp
Data app
Data com.yourcompany.yourexampleapp.voip
Data voip
Data com.yourcompany.yourexampleapp.complication
Data complication
APNs Connections - APNs連接
發(fā)送遠程通知的第一步是與相應(yīng)的APNs服務(wù)器建立連接:
- 開發(fā)服務(wù)器:
api.development.push.apple.com:443 - 生產(chǎn)服務(wù)器:
api.push.apple.com:443
注意:您也可以在與APNs通信時使用端口
2197。 例如,您可以執(zhí)行此操作,以允許APNs通過防火墻,但阻止其他HTTPS流量。
連接到APNs時,您的provider必須支持TLS 1.2或更高版本。您可以使用從開發(fā)人員帳戶獲得的provider客戶端證書,如Creating a Universal Push Notification Client SSL Certificate中所述。
要在沒有APNs provider證書的情況下進行連接,您必須創(chuàng)建一個provider身份驗證token,使用通過your developer account配置的密鑰進行簽名(請參閱Xcode幫助中的Configure push notifications)。擁有此token后,您可以開始發(fā)送推送消息。然后,您必須定期更新token;每個APNs provider身份驗證token的有效間隔為一小時。
APNs允許每個連接有多個并發(fā)流。確切的流數(shù)量因您使用provider證書或身份驗證token而異,并且根據(jù)服務(wù)器負載的不同而不同。不要假設(shè)特定數(shù)量的流。
使用token而不是證書建立與APNs的連接時,在連接上只允許一個流,直到您發(fā)送帶有有效 provider身份驗證token的推送消息。 APNs忽略HTTP / 2 PRIORITY幀,因此不要在您的流上發(fā)送它們。
1. Best Practices for Managing Connections - 管理連接的最佳實踐
通過多個通知保持與APNs的連接;不要反復(fù)打開和關(guān)閉連接。 APNs將快速連接和斷開視為拒絕服務(wù)攻擊。您應(yīng)該保持連接處于打開狀態(tài),除非您知道它將在一段時間內(nèi)處于空閑狀態(tài) - 例如,如果您每天只向用戶發(fā)送一次通知,則可以接受每天使用新連接。
不要為您發(fā)送的每個推送請求生成新的 provider身份驗證token。獲取token后,在token的有效期(即整整一小時)內(nèi)繼續(xù)將其用于所有推送請求。
您可以與APNs服務(wù)器建立多個連接以提高性能。發(fā)送大量遠程通知時,請將它們分配到多個服務(wù)器端點的連接。與使用單個連接相比,通過讓您更快地發(fā)送遠程通知并讓APNs更快地提供它們,這可以提高性能。
如果撤消了 provider證書,或者revoke了用于簽署 provider token的密鑰,請關(guān)閉所有與APNs的現(xiàn)有連接,然后打開新連接。
您可以使用HTTP / 2 PING框架檢查連接的運行狀況。
2. Terminating an APNs Connection - 終止APNs連接
如果APNs決定終止已建立的HTTP / 2連接,它將發(fā)送GOAWAY幀。 GOAWAY幀在其有效載荷中包含帶有reason密鑰的JSON數(shù)據(jù),其值表示連接終止的原因。 有關(guān)reason鍵的可能值列表,請參閱Table 8-6。
正常請求失敗不會導(dǎo)致連接終止。
APNs Notification API - APNs 通知 API
APNs Provider API包含您使用HTTP / 2 POST命令配置和發(fā)送的請求和響應(yīng)。 您使用該請求向APNs服務(wù)器發(fā)送推送通知,并使用該響應(yīng)來確定該請求的結(jié)果。
1. HTTP/2 Request to APNs - HTTP/2 請求 APNs
使用請求向特定用戶設(shè)備發(fā)送通知。
Table 8-1 HTTP/2 request fields
| Name | Value |
|---|---|
:method |
POST |
:path |
/3/device/<device-token> |
對于<device-token>參數(shù),請指定目標設(shè)備的device token的十六進制字節(jié)。
APNs需要使用HP??ACK(HTTP / 2的標頭壓縮),這可以防止重復(fù)的標頭密鑰和值。 APNs為HPACK維護一個小型動態(tài)表。為了避免填寫APNs HPACK表并且必須丟棄表數(shù)據(jù),請按以下方式對header進行編碼 - 尤其是在發(fā)送大量流時:
-
:path值應(yīng)編碼為文字頭字段而不進行索引 -
authorization請求標頭(如果存在)應(yīng)編碼為文字標題字段而不進行索引 - 用于
apns-id,apns-expiration和apns-collapse-id請求標頭的適當編碼根據(jù)它是初始操作還是后續(xù)POST操作的一部分而有所不同,如下所示:- 第一次發(fā)送這些標頭時,使用
incremental indexing對它們進行編碼,以允許將標頭名稱添加到動態(tài)表中。 - 隨后您將發(fā)送這些header,將它們編碼為
literal header fields而不進行indexing編碼。
- 第一次發(fā)送這些標頭時,使用
使用incremental indexing將所有其他標頭編碼為文字標題字段。有關(guān)標頭編碼的詳細信息,請參閱tools.ietf.org/html/rfc7541#section-6.2.1和tools.ietf.org/html/rfc7541#section-6.2.2。
APNs忽略除表8-2中列出的請求標頭之外的請求標頭。
Table 8-2 APNs request headers


消息的正文內(nèi)容是通知的有效負載的JSON字典對象。 不得壓縮正文數(shù)據(jù),其最大大小為4KB(4096字節(jié))。 對于因特網(wǎng)協(xié)議語音(VoIP)通知,主體數(shù)據(jù)最大大小為5KB(5120字節(jié))。 有關(guān)要包含在正文內(nèi)容中的鍵和值的信息,請參閱Payload Key Reference。
2. HTTP/2 Response from APNs - HTTP/2 響應(yīng)APNs
對請求的響應(yīng)具有表8-3中列出的格式。
Table 8-3APNs response headers

表8-4列出了請求的可能狀態(tài)代碼。 這些值包含在響應(yīng)的:status標頭中。
Table 8-4Status codes for an APNs response

對于成功請求,響應(yīng)正文為空。 失敗時,響應(yīng)正文包含一個JSON字典,其中包含表8-5中列出的鍵。 當連接終止時,此JSON數(shù)據(jù)也可能包含在GOAWAY幀中。
Table 8-5 APNs JSON data keys

表8-6 列出了響應(yīng)的JSON有效負載的reason鍵中包含的可能錯誤代碼。
Table 8-6 Values for the APNs JSON reason key


3. HTTP/2 Request/Response Examples for APNs - HTTP/2 APNs 請求響應(yīng)示例
Listing 8-1顯示了為provider證書構(gòu)造的示例請求
// Listing 8-1Sample request for a certificate with a single topic
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-expiration = 0
apns-priority = 10
DATA
+ END_STREAM
{ "aps" : { "alert" : "Hello" } }
LIsting 8-2顯示了為provider身份驗證token構(gòu)造的示例請求
// Listing 8-2 Sample request for a provider authentication token
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-expiration = 0
apns-priority = 10
apns-topic = <MyAppTopic>
DATA
+ END_STREAM
{ "aps" : { "alert" : "Hello" } }
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" } }
Listing 8-3顯示了為包含多個主題的證書構(gòu)建的示例請求。
// Listing 8-3 Sample request for a certificate with multiple topics
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-expiration = 0
apns-priority = 10
apns-topic = <MyAppTopic>
DATA
+ END_STREAM
{ "aps" : { "alert" : "Hello" } }
Listing 8-4顯示了成功推送請求的示例響應(yīng)。
// Listing 8-4Sample response for a successful request
HEADERS
+ END_STREAM
+ END_HEADERS
apns-id = eabeae54-14a8-11e5-b60b-1697f925ec7b
:status = 200
Listing 8-5顯示了發(fā)生錯誤時的示例響應(yīng)。
// Listing 8-5Sample response for a request that encountered an error
HEADERS
- END_STREAM
+ END_HEADERS
:status = 400
content-type = application/json
apns-id: <a_UUID>
DATA
+ END_STREAM
{ "reason" : "BadDeviceToken" }
后記
本篇主要講述了與APNs通信,感興趣的給個贊或者關(guān)注~~~~
