以下所有內(nèi)容均為個(gè)人觀點(diǎn),轉(zhuǎn)載請(qǐng)注明出處<簡(jiǎn)書(shū)--小蝸牛吱呀之悠悠 >,謝謝!
工作的某一天,線上APP的推送服務(wù)突然失效了,源于解決這個(gè)問(wèn)題,整理歸納一下APNS推送和證書(shū)的底層邏輯。
一、推送的簡(jiǎn)單流程

推送大致流程如上圖所示,簡(jiǎn)單來(lái)說(shuō)是服務(wù)端將消息發(fā)送給APNS,然后由APNS將消息推送給手機(jī),在手機(jī)收到消息后進(jìn)行進(jìn)一步的處理,最后展示出來(lái)。這個(gè)流程包括了第三方推送(個(gè)推、極光、友盟等),只是第三方推送在圖中第一第二環(huán)節(jié)增加了處理,代替我們自己的服務(wù)端去和蘋(píng)果交互。另外,圖中所示的Extension環(huán)節(jié)是推送消息在手機(jī)展示前,由APP開(kāi)發(fā)者進(jìn)行處理的最后一環(huán)節(jié),可以修改展示的內(nèi)容,包括文字、增加圖片等,如果想要進(jìn)一步了解這個(gè)環(huán)節(jié)的實(shí)現(xiàn)步驟,可以參考我另一篇文章iOS極光推送帶圖片模式
二、各環(huán)節(jié)具體做了什么事情
前面我們簡(jiǎn)單介紹了一下推送的基本流程,這一節(jié)我們具體聊聊每一個(gè)環(huán)節(jié)到底做了什么,是如何將消息一個(gè)環(huán)節(jié)一個(gè)環(huán)節(jié)成功傳遞的。
1、推送證書(shū)的原理
我們都知道,要實(shí)現(xiàn)iOS的消息推送,需要準(zhǔn)備好推送證書(shū),并且開(kāi)啟推送服務(wù)?,F(xiàn)在我們來(lái)簡(jiǎn)單回顧一下推送證書(shū)是如何申請(qǐng)的。
首先,我們需要從鑰匙串中申請(qǐng)一個(gè)CSR文件
申請(qǐng)步驟:打開(kāi)鑰匙串,如下圖:

填寫(xiě)信息后就可以生成如下圖所示的CSR文件

然后找到蘋(píng)果開(kāi)發(fā)者網(wǎng)站中創(chuàng)建證書(shū)的地方,將CSR上傳,并創(chuàng)建證書(shū),然后將證書(shū)下載下來(lái)安裝即可。

在上述環(huán)節(jié)中,涉及到兩個(gè)東西(CSR文件、.cer后綴的推送證書(shū)),這兩個(gè)文件里面是什么?有什么作用?
蘋(píng)果官方有一對(duì)密鑰,私鑰在蘋(píng)果后臺(tái),公鑰在iOS系統(tǒng)中(出廠后就已經(jīng)攜帶),姑且稱作公鑰(iOS)、私鑰(iOS);
在MAC中請(qǐng)求CSR文件時(shí),會(huì)生成一對(duì)公鑰(mac)、私鑰(mac)。
生成CSR的時(shí)候,由MAC創(chuàng)建公私鑰,并將公鑰(mac)放入CSR,當(dāng)我們將CSR文件上傳到開(kāi)發(fā)者平臺(tái)時(shí),蘋(píng)果會(huì)用私鑰(iOS)對(duì)公鑰(mac)進(jìn)行簽名,生成.cer證書(shū)文件。也就是說(shuō),CSR攜帶公鑰(mac),.cer證書(shū)包含了加密后的CSR和一些其他的權(quán)限信息。
那推送證書(shū)在推送的過(guò)程是怎么發(fā)揮作用的呢?在理解這個(gè)問(wèn)題之前,我們先了解一下app是怎么安裝到手機(jī)上的。
2、APP安裝時(shí)簽名、驗(yàn)簽過(guò)程
1、首先,在使用Xcode對(duì)APP進(jìn)行打包的時(shí)候,會(huì)用私鑰(mac)對(duì)包進(jìn)行簽名,然后把描述文件一起放到包里。
由于發(fā)布APP需要發(fā)布證書(shū)(product.cer),根據(jù)我們前面的介紹,這個(gè)證書(shū)也是攜帶了CSR的,并且是被私鑰(iOS)加密的。
2、在完成第一步后,Xcode會(huì)將發(fā)布證書(shū)、設(shè)備信息、APPID等內(nèi)容一并使用私鑰(iOS)再加密簽名一次
3、最后,將步驟1、步驟2的產(chǎn)物一起組成ipa包,然后發(fā)布到App Store。
4、當(dāng)用戶下載APP安裝時(shí),手機(jī)會(huì)用出廠時(shí)就攜帶的公鑰(iOS)對(duì)ipa包解密(步驟2的產(chǎn)物兩次解密),得到步驟1的產(chǎn)物、發(fā)布證書(shū)、設(shè)備信息等內(nèi)容。
到這里,一個(gè)ipa包被拆解為這些內(nèi)容:用私鑰(mac)對(duì).app包簽名后的描述文件、用私鑰(iOS)對(duì)CSR簽名的證書(shū)。
5、用公鑰(iOS)對(duì)證書(shū)解簽,得到CSR,并從CSR文件中拿到公鑰(mac)
6、用步驟5得到的公鑰(mac)再去解簽描述文件,得到.app包。
在上述過(guò)程中,公私鑰(iOS)主要起到蘋(píng)果授權(quán)的作用,公私鑰(mac)主要起到校驗(yàn)包是否被篡改的作用。
3、推送是如何通信鑒權(quán)的
了解了APP安裝的流程后,我們知道,在APP打包過(guò)程,會(huì)將證書(shū)等信息放到包里進(jìn)行加密,推送證書(shū)也就是這個(gè)環(huán)節(jié)被放到了包里。那么推送是怎么完成閉環(huán)的呢?接下來(lái)我們看下面這張圖:

完成完整的推送,大致有下面幾個(gè)環(huán)節(jié):
步驟一:?jiǎn)?dòng)APP時(shí),通常會(huì)去請(qǐng)求推送權(quán)限,當(dāng)用戶點(diǎn)擊允許后,手機(jī)就會(huì)拿著設(shè)備標(biāo)識(shí)、推送證書(shū)發(fā)送給APNS服務(wù)器,蘋(píng)果收到這些信息后,會(huì)根據(jù)推送證書(shū)、設(shè)備標(biāo)識(shí)、APP信息去驗(yàn)證是否具有推送權(quán)限,如果有推送權(quán)限,蘋(píng)果會(huì)將這臺(tái)設(shè)備信息放入推送列表中。
步驟二:在蘋(píng)果通過(guò)權(quán)限校驗(yàn)后,會(huì)根據(jù)設(shè)備標(biāo)識(shí)和APP標(biāo)識(shí)生成一個(gè)deviceToken,并將這個(gè)deviceToken返回給APP。
步驟三:deviceToken送達(dá)手機(jī)后,會(huì)在APP中的下述方法告知開(kāi)發(fā)者
-(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
當(dāng)這個(gè)方法回調(diào)時(shí)攜帶deviceToken后,根據(jù)接入推送服務(wù)的不同,可以分為自己服務(wù)器和第三方服務(wù)器。如果是自己的服務(wù)器實(shí)現(xiàn)推送(七魚(yú)),則將deviceToken直接傳給后端即可;如果是接入了第三方SDK,則傳給第三方服務(wù)商的后端,后續(xù)的推送則由第三方完成
步驟四:當(dāng)服務(wù)器有消息需要推送給APP時(shí),服務(wù)器會(huì)攜帶推送證書(shū)和推送的消息體去通知APNS(如果是第三方推送,由服務(wù)器推送消息給第三方后端,由第三方去連接APNS)。
步驟五:APNS收到需要推送的消息后,對(duì)攜帶的證書(shū)進(jìn)行鑒權(quán),如果通過(guò),則根據(jù)APNS的推送規(guī)則,將消息下發(fā)給手機(jī)。
步驟六:當(dāng)手機(jī)收到來(lái)自蘋(píng)果的推送消息后,在展示前會(huì)先判斷開(kāi)發(fā)者是否有實(shí)現(xiàn)推送消息攔截,如果沒(méi)有,則直接展示;如果有實(shí)現(xiàn)攔截,則交給開(kāi)發(fā)者處理。
三、證書(shū)被刪或者過(guò)期
如果無(wú)意之中把推送證書(shū)刪了,或者是證書(shū)過(guò)期失效了,這時(shí)候該怎么辦?
首先需要將原有的無(wú)效的證書(shū)清理干凈,并在開(kāi)發(fā)者中心找到你APP的標(biāo)識(shí)

進(jìn)入到自己APP的服務(wù)列表里,找到推送服務(wù),重新編輯或者創(chuàng)建證書(shū)

接下來(lái)的步驟就和上文中提到的步驟一模一樣了。