先簡單介紹下push的機制數據庫
客戶端經過安全
(void)registerForRemoteNotificationTypes:(UIRemoteNotificationType)types服務器
這個函數向APNs(Apple Push Service)註冊push,types可標明接收的push的類型,聲音,數字等。app
(void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken;iphone
當app成功註冊通知後,會調用這個函數,並把deviceToken返回給應用。ide
而後咱們的程序就會把返回的這個deviceToken以及設備的udid及軟件版本(淘寶 for iPhone仍是淘寶 for iPad)及系統版本,用戶名等發送到咱們的服務器(下圖中的provider)上,而後存儲在數據庫裏。整個獲取device token的過程可參見下圖所示:函數
在須要發送push時,咱們的服務端就會取出要發送的設備的device token,而後如下圖所示的結構,組成符合特定結構的字符串,而後將其發送到的APNs測試
APNs能夠根據與APNs創建鏈接的Provider所使用的證書判斷是要哪一個app請求發送的notification,繼而把這個notification發送到的設備上。加密
下圖爲一個簡單的從Provider到Device發送push的過程:spa
device token究竟是什麼呢? 不一樣的app的device token相同麼? 一個設備會產生多個device token麼? 一個的device token可能對應多個UDID麼?
結論:device token是對APNs來講,設備的標識符,與app無關,因此同一臺設備上,不一樣的app得到的device token是同樣的; 一個設備可能會產生多個device token, 一個device token也可能對應多個UDID,下面進行解釋。
device token是什麼?
文檔中以下描述的:
對於APS來講,token是設備的標識符。device token不一樣於UIDevice的uniqueIdentifier(即UDID),由於出於安全和隱私緣由,當設備被擦除後,token必須變化。
因此也就是說,通常狀況下,token是不變的,可是在設備被擦除後,token會變的。
今天無意說在咱們的服務器上的數據庫裏,存在同一個UDID對應有多個token的狀況,以前是沒有考慮到設備擦除的狀況,因此就懷疑是否是同一個 設備上同時裝了taobao4iphone和taobao4ipad,而token是與app關聯的,因此產生的這種狀況,因而就找了ipad來作 測試,結果發現taobao4iphone和taobao4ipad收到的token是相同的,因此token應該是與app無關的,而是針對設備的(文 檔上也是如此描述的),是設備的標識,那除了設備被擦除的狀況外,設備的device token 應該是相同的,但是給他查出來的他的iPad的token和我log出來的device token是不一樣的,後來就想到了,push是有兩套的,development和product,即調試和release,在這兩種狀況下,服務端使用 的push證書是不同的,而程序使用的證書也不同,那同一個設備在development和distribution狀況下收到的device token是否同樣呢,因而就作了實驗,實際結果以下
實驗設備:
能夠看出,同一個設備在development和distribution狀況下,收到的device token是不一樣的,而token是與app無關的。
綜合文檔及上述實驗結果能夠獲得如下結果:
同一個udid對應有不一樣的device token的狀況暫時有以下兩種:
設備擦除過,token變化過,老的新的都存儲在數據庫裏
設備同時裝過development和distribution的程序
不知道還有沒有其它緣由形成的同一個設備有不一樣的device token的狀況,你們若是有什麼相關的經驗,能夠補充一下。
無意說數據庫裏也有同一個device token對應多個UDID的狀況,這種狀況就比較詭異了,按理說不該該的,比較APNs把token做爲設備的標識的,若是同一個device token能夠對應多個udid,那發push不是就會混亂了麼,在網上查了相關資料,發現還真的有這種狀況,
設備令牌是怎麼生成的呢?是每次創建TLS鏈接時,APNS經過前一層次(TLS層)裏咱們提到的每臺正常的iPhone惟一的設備證書(unique device certificate),並用令牌密鑰(token key)加密生成的。
最重要的部分——每臺iPhone獨有的設備證書和密鑰的來歷
正常的iPhone刷系統以後,是沒有設備證書和密鑰的。這就是爲何iPhone會須要鏈接到iTunes上進行激活——激活過程當中,Apple會分配給每臺iPhone獨一無二的設備證書(device certificate)和密鑰(key) 。
iPhone OS 3.X 使用blacksn0w進行解鎖 的過程,是不通過iTunes的,而blacksn0w自己又不生成對應的設備證書(device certificate)和密鑰(key) ,所以這樣解鎖完的iPhone根本不可能與APNS創建任何的TLS連接,Push天然廢了。
但當多個iPhone的設備證書(device certificate)徹底一致時,就存在必定概率使得多個iPhone得到相同的設備令牌(device token)
要修補這個問題,惟一的辦法就是從新生成惟一且有效的設備證書(device certificate)和密鑰(key) 。因而,最先,dev team推出了一個測試版補丁,Push fix by dev team(經過他們的twitter發佈的,所以官網沒有消息)。這個補丁初期頗有效。可是僅在iPhone 2G上比較正常。以後某人士發佈pushfix 1.0了。因爲使用了不一樣的生成方法,所以在新版本iPhone上也正常工做了。因而風靡一時。
然而,以上兩個補丁都有嚴重的隱患——他們使用了一個固定的證書做爲設備證書(device certificate)。所以在不一樣iPhone上的區別僅僅在於生成的密鑰(key)不一樣。 (待確認)
而隨着這兩個補丁的使用人數不斷增長,使得出現得到相同設備令牌(device token)的iPhone數量大大增長了。
當這些相同設備令牌(device token)的iPhone上啓用了同一個應用程序的Push的時候,就極有可能出現彼此間的Push串發的現象。——如某論壇目前N多人抱怨QQ的Push到別人iPhone上的狀況就是如此。
以上大概解釋了同一個device token對應多個UDID的緣由,
因爲咱們後續也會把與用戶相關的信息push到用戶的設備上,因此這個問題,咱們也要考慮下應該怎麼處理,不然也可能會出現,收到別人的物流的push。。。
另外,因爲iOS5.0後,UIDevice中的uniqueIdentifier會逐步被廢棄,因此,後面的版本中,咱們會使用把設備的mac地 址md5計算後的結果作爲設備的惟一標識,用其去代替UDID上傳到咱們的服務端上,可是不管是UDID仍是mac地址的md5值,都只是做爲設備的標 識,在發送push時,惟一須要與設備相關的信息就是device token,因此這個應該不影響咱們的push。