1. 程式人生 > >iOS裝置唯一標識探討

iOS裝置唯一標識探討

      首先iOS中獲取裝置唯一標示符的方法一直隨版本的更新而變化。iOS 2.0版本以後UIDevice提供一個獲取裝置唯一識別符號的方法uniqueIdentifier,通過該方法我們可以獲取裝置的序列號,這個也是目前為止唯一可以確認唯一的標示符。好景不長,因為該唯一識別符號與手機一一對應,蘋果覺得可能會洩露使用者隱私,所以在 iOS 5.0之後該方法就被廢棄掉了;iOS 6.0系統新增了兩個用於替換uniqueIdentifier的介面,分別是:identifierForVendor,advertisingIdentifier,但這兩個介面會在應用重新安裝時改變數值,並不是唯一的標示符,所以開發者改為使用WiFi的mac地址來取代;iOS 7中蘋果又封殺mac地址,所以開發者再次改變思路使用KeyChain來儲存獲取到的UDID,這樣以後即使APP刪了再裝回來,也可以從KeyChain中讀取回來。

首先儲存裝置的UUID,可以使用類方法+ (id)UUID 是一個類方法,呼叫該方法可以獲得一個UUID。通過下面的程式碼可以獲得一個UUID字串:

 NSString *uuid = [[NSUUID UUID] UUIDString];

也可以儲存在iOS 6中新增的Vindor標示符 (IDFV-identifierForVendor),獲取這個IDFV的新方法被新增在已有的UIDevice類中。跟advertisingIdentifier一樣,該方法返回的是一個NSUUID物件。

NSString *idfv = [[[UIDevice currentDevice] identifierForVendor] UUIDString
];

如果使用者解除安裝了同一個vendor對應的所有程式,然後在重新安裝同一個vendor提供的程式,此時identifierForVendor會被重置,所以這裡要用到KeyChain來儲存。
KeyChain(鑰匙串)是使用蘋果裝置經常使用的,通常要除錯的話,都得安裝證書之類的,這些證書就是儲存在KeyChain中,還有我們平時瀏覽網頁記錄的賬號密碼也都是記錄在KeyChain中。iOS中的KeyChain相比OS X比較簡單,整個系統只有一個KeyChain,每個程式都可以往KeyChain中記錄資料,而且只能讀取到自己程式記錄在KeyChain中的資料。iOS中Security.framework框架提供了四個主要的方法來操作KeyChain:

  • SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);//查詢OSStatus
  • SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result); //新增OSStatus
  • SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);//更新KeyChain中的ItemOSStatus
  • SecItemDelete(CFDictionaryRef query)//刪除KeyChain中的ItemOSStatus

  這四個方法引數比較複雜,一旦傳錯就會導致操作KeyChain失敗,文件中介紹的比較詳細,大家可以查查官方文件。而蘋果提供的KeyChain使用起來略麻煩,所以這裡推薦一個第三方庫SSKeyChains.SSKeyChains對蘋果安全框架API進行了簡單封裝,支援對儲存在鑰匙串中密碼、賬戶進行訪問,包括讀取、刪除和設定。SSKeyChains使用簡單,通過例項程式碼便可掌握。


原文連結:http://www.jianshu.com/p/7ad22ca88b83

接下來我想跟大家探討的是如何通過“合法”的手段來儘量拿到不會輕易發生變化的“唯一標識”。

移動統計平臺都用啥來標識裝置呢?
研究了下國內兩大移動統計平臺友盟和TalkingData 的SDK
友盟用的是 Openudid + IDFA
TalkingData用的是 Keychain + IDFA

Openudid

Openudid是一個github上一個開源的專案: 地址
原理是利用iOS系統中的UIPasteboard剪貼簿類,它用 app-special pastboards 來儲存一160位的隨機字串,存取的方式類似字典的key-value。 app-special pastboards 可持久儲存字串,即使開關機、解除安裝應用,並能在app之間共享。Openudid的第一次訪問的時候用key去檢查剪貼簿內是否存在對應的value(隨機數),如果不存在就生成一個並存儲在Pasteboard中,第二次訪問的時候就可以直接取到而不去生成新的隨機數。
但是iOS7之後,蘋果封堵了剪貼簿通訊的漏洞,iOS之前是所有的應用都可以共享同一個剪貼簿儲存內容,現在只有在同一CFBundleIdentifier標識下的App才能共享內容,如com.koudai.a和com.koudai.b,它們的com.mycompany部分是一樣的,就能共享(請用真機測試,模擬器會有偏差)。

Keychain

keychain中文翻譯為鑰匙串,是蘋果用來儲存密碼和證書的一塊加密儲存區域,目的是為了幫助使用者安全儲存應用或者瀏覽器的密碼,省去了很多輸入密碼和記密碼的麻煩。keychain不是儲存在手機的沙盒內,而是手機的某個公共區域,手機重啟和應用解除安裝,都不會對這片儲存區域造成影響,因為是加密儲存不存在被其他應用修改的問題,所以就有人拿keychain來儲存唯一標識。
再Max OS上訪問keychian需要提供使用者的登入密碼,而在iOS上使用者原則上只能訪問本應用儲存的keychain,除非是同一個provisioning 證書的兩個應用,比如美團的貓眼就能讀取美團app中的keychian,使用者第一次開啟貓眼app就會彈出提示,使用者可以讀取美團的賬號和密碼免登入進入貓眼。keychain是根據provision 證書來鑑定許可權,所以app的版本需要使用同一個,否則版本之間會失效。使用者恢復出廠設定,機器上的keychain會被清除,但如果事先對手機進行了備份,keychain儲存的內容依然有效。順便提一句keychain在越獄的機器上是可以被匯出的,所以儲存敏感資訊前請加密。

NSUUID

上節keychain把儲存的問題解決了,那存什麼來保證每個裝置的id都是唯一的呢?大部分應用存的是UUID,它是蘋果再iOS6後提供的一個獲取大隨機數的方法。UUID, 全球獨立標識(Globally Unique Identifier),據wiki說UUID隨機數演算法得到的數重複概率為170億分之一,170億分之一什麼概念?可以告訴你買一注雙色球的中獎概率是1700萬分之一。隨機演算法有幾套,包括用時間戳、MD5什麼的,蘋果是遵循的RFC 4122 version 4,大家可以去google下。

NSString *uuid = [[NSUUID UUID] UUIDString];

每次呼叫此方法得到的UUID肯定是不一樣的,所以必須藉助於持久化儲存。

IDFA

IDFA這是iOS 6中另外一個新的方法,是AdSupport.framework框架中ASIdentifierManager單例提供了一個方法advertisingIdentifier,通過呼叫該方法會返回一個的NSUUID例項。廣告標示符也是由系統儲存著的,還原系統和在(設定程式-> 通用 -> 關於本機 -> 廣告 -> 還原廣告標示符)設定中重置都會被還原。蘋果對IDFA的使用做了限制,使用IDFA但未整合任何廣告服務的應用稽核都會被拒,應用中使用了IDFA的話,必須在iTunes Connect中的上傳頁面進行相應的設定,否則上傳應用稽核的時候會出現錯誤。

當然還有許多其他的ID可以用來標識裝置,我文中提到了只是自己認為相對靠譜的方法,如果讓我選擇的話,我會用keychain儲存NSUUID的方法,畢竟一個使用者重置系統是小概率事件,即使有人真的想偽造使用者量做一次系統重置的成本非常高。如果大家有更好的獲取iOS裝置唯一標示的方法,不妨留言討論。


原文連結:http://www.jianshu.com/p/b83b0240bd0e
著作權歸作者所有,轉載請聯絡作者獲得授權,並標註“簡書作者”。