前言
? ? ? 在做GCM推送的時(shí)候,遇到GCM Server返回“Invalid Package Name”的錯(cuò)誤信息季春。一開始以為是服務(wù)端的Server API Key與APP沒有匹配上洗搂,后來查明是后臺(tái)人員在發(fā)往GCM Server的消息中加了restricted_package_name這個(gè)字段,并且傳了錯(cuò)誤的值载弄。于是引發(fā)了以下對(duì)restricted_package_name字段的探究耘拇。
restricted_package_name的含義
官網(wǎng)是這樣解釋的:
This parameter specifies the package name of the application where the registration tokens must match in order to receive the message.
即是說,只有restricted_package_name字段中指定包名的應(yīng)用才能接收到推往設(shè)備的消息侦锯。
restricted_package_name的驗(yàn)證
? ? ? 于是驼鞭,我們嘗試在推送消息中加入restricted_package_name字段,并賦以不同的value進(jìn)行測(cè)試尺碰,得到如下結(jié)論:
? ? ?* 正確的包名挣棕,推送成功。
? ? ?*?空字符串亲桥,推送成功洛心。
? ? ?* 錯(cuò)誤的包名,推送失敗题篷。返回“Invalid Package Name”錯(cuò)誤信息词身。
? ? ? 由以上的測(cè)試,可以看出:只要restricted_package_name予以有效賦值番枚,GCM Server就會(huì)發(fā)往指定包名的應(yīng)用法严。但是损敷,如果推送的registration ids并不是為該應(yīng)用分配的,則會(huì)報(bào)“Invalid Package Name”深啤,信息不會(huì)被發(fā)送拗馒。
restricted_package_name是否必要?
首先我們先來理一下推送流程:
1.在GCM官網(wǎng)創(chuàng)建應(yīng)用Create or choose an app溯街。我們填寫APP packagename诱桂,由此生成Server API Key以及APP SenderId。
2.APP通過SenderId呈昔,獲取registration id(類似iOS的deviceToken)挥等,并發(fā)給Server。
3.Server通過API Key發(fā)送消息到registration id標(biāo)識(shí)的設(shè)備上的APP堤尾。
? ? ? 從流程中肝劲,可以看到API Key、SenderId郭宝、registration id是相互關(guān)聯(lián)的涡相。并且,我們似乎可以猜測(cè)剩蟀,GCM Server收到推送請(qǐng)求時(shí)能夠判斷API Key與registration id是否匹配催蝗,并且是發(fā)往哪一個(gè)應(yīng)用的。
? ? ? 為什么說能識(shí)別出發(fā)往哪一個(gè)應(yīng)用育特?這主要是出于兩個(gè)方面:一是創(chuàng)建應(yīng)用時(shí)需要填寫packagename丙号,通過API Key可以找出對(duì)應(yīng)的packagename;二是registration id缰冤,官網(wǎng)寫著“a token that can identify and authorize the instance of the application on the device.This is similar to an OAuth2 token except, it applies to the application instance instead of a user.”即它至少包含device和application兩個(gè)信息犬缨,同樣可以拿到packagename;而且從上文“Invalid Package Name”的錯(cuò)誤信息也能說明registration id可以獲取packagename棉浸。
? ? ? 寫到這里怀薛,估計(jì)大家都困惑了。既然GCM Server能通過API Key和registration id識(shí)別packagename迷郑,那restricted_package_name是不是顯得有點(diǎn)多余枝恋?答案并非如此,我們只是說GCM Server可以通過API Key和registration id分別獲取對(duì)應(yīng)的packagename并校驗(yàn)其一致性嗡害,但不代表GCM Server有這樣做焚碌!一切靠實(shí)際結(jié)果來驗(yàn)證。
? ? ? 接下來霸妹,我們就來做一下測(cè)試:
前期準(zhǔn)備:
* 一臺(tái)安卓設(shè)備
* APP 1十电,對(duì)應(yīng)Server 1、SenderId 1、API Key 1
* APP 2鹃骂,對(duì)應(yīng)Server 2台盯、SenderId 2、API Key 2
* 不加restricted_package_name字段
測(cè)試案例?1:驗(yàn)證“GCM Server是否會(huì)校驗(yàn)API Key與registration id的一致性”
為了好理解一點(diǎn)畏线,我們可以假設(shè)這樣一個(gè)場(chǎng)景:4月1日想惡作劇一下爷恳,打算用我們的服務(wù)器往別人家APP推送一條搞怪的消息。
注意:在案例中registration id簡(jiǎn)稱為token
測(cè)試過程:
1.APP 2通過SenderId 2生成一個(gè)token 22(22表示由APP 2利用SenderId 2生成的)象踊。
2.Server 1拿到這個(gè)token 22,通過API Key 1推送消息到token 22棚壁。
測(cè)試結(jié)果:
GCM Server返回“MismatchSenderId”的錯(cuò)誤信息杯矩。
測(cè)試案例 2:驗(yàn)證“GCM Server是否會(huì)校驗(yàn)API Key與registration id對(duì)應(yīng)packagename的一致性”
同樣,我們可以假設(shè)這樣一個(gè)場(chǎng)景:一個(gè)黑客破解了我們APP的源碼袖外,拿到我們的SenderId史隆,然后自己寫一個(gè)APP利用這個(gè)SenderId生成對(duì)應(yīng)token,并發(fā)給我們服務(wù)器注冊(cè)曼验,這樣我們服務(wù)器推送消息時(shí)也會(huì)推給黑客的APP泌射。
測(cè)試過程:
1.APP 2通過SenderId 1生成一個(gè)token 21(21表示由APP 2利用SenderId 1生成的);
2.Server 1拿到這個(gè)token 21鬓照,通過API Key 1推送消息到token 21熔酷。
測(cè)試結(jié)果:
Server 1推送成功,APP 2能夠接收到推送消息豺裆。
測(cè)試案例 3:為了進(jìn)一步驗(yàn)證拒秘,我們讓Server 1同時(shí)往token 11、token21推送同一條消息臭猜,結(jié)果APP1躺酒、APP2都能接收到推送消息。
結(jié)論:
1.GCM Server會(huì)校驗(yàn)API Key與registration id的一致性蔑歌。
2.GCM Server不會(huì)校驗(yàn)API Key與registration id對(duì)應(yīng)APP packagename的一致性羹应。
? ? ? 以上,我們就可以明白了次屠,只要“API Key”與“registration id對(duì)應(yīng)的SenderId”能夠匹配上园匹,就可以推送成功。GCM Server并不管是哪一個(gè)應(yīng)用劫灶!restricted_package_name的作用不言而喻偎肃。
>> 同樣,我們對(duì)此進(jìn)行了驗(yàn)證浑此。
測(cè)試案例 4:在基于案例3的基礎(chǔ)上累颂,加入restricted_package_name。首先賦以APP 1的packagename,結(jié)果是:token 11(APP 1)推送成功紊馏,token 21(APP 2)報(bào)“Invalid Package Name”錯(cuò)誤信息料饥;其次改為APP 2的packagename,結(jié)果是:token 11(APP 1)報(bào)“Invalid Package Name”錯(cuò)誤信息朱监,token 21(APP 2)推送成功岸啡。
為什么GCM Server不校驗(yàn)?
這也不能說是Bug赫编,可能是Google工程師覺得沒有必要巡蘸,也可能是GCM允許同個(gè)開發(fā)者的多個(gè)應(yīng)用可以共享同一套API Key和SenderId吧。
在questions about security nature of GCM這個(gè)帖子中擂送,一位開發(fā)者提出了類似案例2中的場(chǎng)景悦荒,對(duì)此,Google工程師在答復(fù)中發(fā)布了“加入restricted_package_name字段”的消息嘹吨,并且指出真正的問題--“為什么APP 2可以在Server 1上注冊(cè)token搬味?”他建議:向Server注冊(cè)token時(shí),應(yīng)進(jìn)行加密處理或者一定的校驗(yàn)蟀拷,以保證token的合法性碰纬。
總結(jié)
GCM 同一套API Key和SenderId允許發(fā)給多個(gè)應(yīng)用,可以通過restricted_package_name來指定某個(gè)應(yīng)用问芬。
參考文章
groups.google.com/forum/#!topic/android-gcm/M-EevBitbhQ
android - Why is restricted_package_name used? - Stack Overflow
developers.google.com/cloud-messaging/http-server-ref#error-codes