UDID是什嗎?
UDID的全稱是Unique Device Identifier,顧名思義,它就是蘋果IOS裝置的唯一識別碼,它由40個字元的字母和數字組成。
UDID有什麼用?
移動網路可利用UDID來識別行動裝置,如iPhone和iPad。UDID對每台裝置而言都是唯一的,從而成為了廣告公司、市場分析機構和APP測試系統跟蹤使用者行為的工具 + 生產力。
目前使用UDID主要原因分為:
1)用於統計與分析,例如第三方統計工具Flurry、友盟等,廣告商ADMOB等;
2)將UDID作為使用者ID來唯一識別使用者,省去使用者名稱,密碼等註冊過程。
由此可見UDID對於IOS應用開發人員說,是個很重要的資訊(雖然越獄的裝置通過某些工具可以改變裝置的UDID)。但是,從IOS5.0開始,蘋果宣布將不再支援用以下方法擷取裝置的UDID。
[cpp] view plaincopy
- [UIDevice currentDevice] uniqueIdentifier];
最近又爆出蘋果App Store禁止訪問UDID的應用上架,所以開發人員應儘快棄用UDID,去尋找另外的替代方案。
我為此也花了不少時間去尋找比較好的替代方案,下面一一道來:
一、蘋果公司建議的UUID替代方案
[cpp] view plaincopy
- -(NSString*) uuid {
- CFUUIDRef puuid = CFUUIDCreate( nil );
- CFStringRef uuidString = CFUUIDCreateString( nil, puuid );
- NSString * result = (NSString *)CFStringCreateCopy( NULL, uuidString);
- CFRelease(puuid);
- CFRelease(uuidString);
- return [result autorelease];
- }
蘋果公司建議採用上述代碼為應用產生唯一標識字串。開發人員可以在應用第一次啟動時調用一次,然後將該串儲存起來,以便以後替代UDID來使用。顯而易見,這種方法問題很多。如果使用者刪除該應用再次安裝時,又會產生新的字串,所以不能保證唯一識別該裝置;如果你從一台舊裝置中備份檔案到新裝置中,兩台裝置就擁有相同的CFUUID;如果你從臨時檔案中備份作業系統,就會出現一個裝置裡存在不同CFUUID的情況。
二、開源方案OpenUDID
貢獻者在readme文檔中說:
OpenUDID is a drop-in replacement for the deprecated [UIDevice uniqueIdentifier] a.k.a. UDID on iOS, and otherwise is an industry-friendly equivalent for iOS and Android.
The agenda for this community driven project is to: - Provide a reliable proxy and replacement for a universal unique device identifier. That is, persistent and sufficiently unique, on a per device basis. - NOT use an obvious other sensitive unique identifier (like the MAC address) to avoid further deprecation and to protect device-level privacy concerns - Enable the same OpenUDID to be accessed by any app on the same device - Supply open-source code to generate and access the OpenUDID, for iOS and Android - Incorporate, from the beginning, a system that will enable user opt-out to match Apple’s initial intent.
願景很好,也確實沒有用到MAC地址,同時能保證同一台裝置上的不同應用使用同一個OpenUDID。但是仔細分析,還是能發現問題。
OpenUDID產生唯一識別碼的代碼是:
[cpp] view plaincopy
- unsigned char result[16];
- const char *cStr = [[[NSProcessInfo processInfo] globallyUniqueString] UTF8String];
- CC_MD5( cStr, strlen(cStr), result );
- _openUDID = [NSStringstringWithFormat:
- @"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%08x",
- result[0], result[1], result[2], result[3],
- result[4], result[5], result[6], result[7],
- result[8], result[9], result[10], result[11],
- result[12], result[13], result[14], result[15],
- arc4random() % 4294967295];
這裡使用了NSProcessInfo類。
當裝置上第一個使用OpenUDID解決方案的應用第一次調用時,確實會產生一個唯一的識別碼。同時,為了與官方的UDID位元相同,還在MD5值後面追加了8位隨機碼。然後,該方案使用到了NSUserDefaults類(應用設定)。應用將擷取到的唯一識別碼儲存到應用的UserDefaults中,如果程式以後需要使用唯一識別碼,就從UserDefaults中擷取,這樣就保證可以拿到同一個識別碼。但是,如果使用者刪除了應用,UserDefaults同樣會被清空,為了避免重建唯一識別碼,該方案還使用到了UIPasteboard類(裝置剪下板)。應用在將唯一識別碼儲存到UserDefaults的同時,也會將其儲存到以特殊的key標識的UIPasteboard中。代碼如:
[cpp] view plaincopy
- UIPasteboard* slotPB = [UIPasteboardpasteboardWithName:availableSlotPBid create:YES];
- [slotPB setData:[NSKeyedArchiver archivedDataWithRootObject:dict] forPasteboardType:kOpenUDIDDomain];
其中availableSlotPBid是一個字串key,首碼是“org.OpenUDID.slot.”,點後面加上數字。這個數字預設是從0到99(當然你可以修改原始碼使它更大或者更小)。
如果裝置上安裝了第二個使用OpenUDID解決方案的應用,當應用調用產生OpenUDID的方法時,將會從UIPasteboard中擷取唯一識別碼(遍曆key從0到99的UIPasteboard),這裡取到的就是之前第一個應用儲存到UIPasteboard中的。也就是說,只要使用者裝置上有一個使用了OpenUDID的應用存在時,其他後續安裝的應用如果擷取OpenUDID,都將會獲得第一個應用產生的那個。
看起來似乎很好,很複雜。但是仔細想想,還是有問題,如果把使用了OpenUDID方案的應用全部都刪除,再重新擷取OpenUDID,此時的OpenUDID就跟以前的不一樣了(本人測了一下,確實如此)。可見,這種方法還是不保險。
三、開源方案SecureUDID
稍微看了下SecureUDID源碼,發現其與OpenUDID其實差不多,只是初始擷取的唯一識別碼稍有不同。同時,從作者的Readme文檔中可見,這個方案同樣存在很多問題。如原文:
Is this a true UDID replacement?
SecureUDID has two properties that you should know about before you use it. First, as indicated above, the identifier is not derived from hardware attributes. Second, the persistence of an identifier cannot be guaranteed in all situations. This means that, while unlikely, it is technically possible for two distinct devices to report the same identifier, and for the same device to report different identifiers. Consider this carefully in your application. Here is a list of situations where this identifier will not exhibit the uniqueness/persistence of a traditional UDID.
* The user has opted-out of the SecureUDID system, in which case you will receive a well-formed string of zeroes.
* Device A is backed up and then restored to Device B, which is an identical model. This is common when someone breaks their phone, for example, and is likely desirable: you will receive Device A's SecureUDID.
* The SecureUDID data is removed, via user intervention, UIPasteboard data purge, or by a malicious application.
* The SecureUDID backing store becomes corrupt.
* All SecureUDID applications are uninstalled from a device, followed by a UIPasteboard data purge.
我發現,其實前面的OpenUDID也基本存在以上問題,只是作者沒寫出來。看來還是SecureUDID的貢獻者比較厚道。
四、與WIFI MAC地址相關
網上同樣有一些與WIFI MAC地址相關的替代方案,主要分三種:第一種直接使用“MAC Address”;第二種,使用“MD5(MAC Address)”;第三種,“MD5(MAC Address+CFBundleIdentifier)”。github上有個開源項目(UIDevice-with-UniqueIdentifier-for-iOS-5)實現了這幾種方法。
使用這種方法也存在問題:1、市面上有部分機器(雖然數量極少,但是本人在使用過程中確實發現過這種情況)無法獲得MAC地址,有人說這部分機器是聯通閹割無WIFI版的,具體不得而知了。2、MAC地址跟UDID一樣,存在隱私問題。蘋果現在禁用UDID,不能保證以後不會禁用MAC地址。
參考地址:http://blog.csdn.net/jwzbskywz/article/details/7703140