1. 程式人生 > >iOS得到裝置唯一標識的各種方案及推薦使用方案的介紹

iOS得到裝置唯一標識的各種方案及推薦使用方案的介紹

由於我們後臺判斷App登入時根據唯一標識來判斷的在不同終端登入的,如果唯一標識不一樣,說明是換了裝置,但是我們的使用者名稱密碼是我們同一系列的app公用的,所以得保證同一公司旗下的app在同一裝置下的唯一標識是同一個,避免出現同一裝置登陸同一系列其他app時提示換了裝置,說個簡單的例子

如:我的使用者名稱是aaa,淘寶和支付寶可以共用,在我的手機上我可以用aaa同時登陸淘寶和支付寶,但是如果我在另一個手機上使用aaa,那麼就需要提示使用者換了裝置

1.UDID(Unique Device Identifier)

//UUID , 已廢除

NSString *udid = [[UIDevice currentDevice] uniqueIdentifier];

UDID的全稱是Unique Device Identifier,它就是蘋果iOS裝置的唯一識別碼,它由40位16進位制數的字母和數字組成(越獄的裝置通過某些工具可以改變裝置的UDID)。行動網路可利用UDID來識別移動裝置,但是,從IOS5.0(2011年8月份)開始,蘋果宣佈將不再支援用uniqueIdentifier方法獲取裝置的UDID,iOS5以下是可以用的。蘋果從iOS5開始就移除了通過程式碼訪問UDID的許可權。從2013年5月1日起,試圖訪問UIDIDs的程式將不再被稽核通過,替代的方案是開發者應該使用“在iOS 6中介紹的Vendor或Advertising標示符”。所以UDID是絕對是不能再使用了。

為什麼蘋果反對開發人員使用UDID?  
iOS 2.0版本以後UIDevice提供一個獲取裝置唯一識別符號的方法uniqueIdentifier,通過該方法我們可以獲取裝置的序列號,這個也是目前為止唯一可以確認唯一的標示符。 許多開發者把UDID跟使用者的真實姓名、密碼、住址、其它資料關聯起來;網路窺探者會從多個應用收集這些資料,然後順藤摸瓜得到這個人的許多隱私資料。同時大部分應用確實在頻繁傳輸UDID和私人資訊。 為了避免集體訴訟,蘋果最終決定在iOS 5 的時候,將這一慣例廢除,開發者被引導生成一個唯一的識別符號,只能檢測應用程式,其他的資訊不提供。現在應用試圖獲取UDID已被禁止且不允許上架。

2.UUID(Universally Unique Identifier)

  • 是基於iOS裝置上面某個單個的應用程式,只要使用者沒有完全刪除應用程式,則這個UUID在使用者使用該應用程式的時候一直保持不變。如果使用者刪除了這個應用程式,然後再重新安裝,那麼這個UUID已經發生了改變
  • 同一裝置上的不同應用的UUID是互斥的,即能在改裝置上標識應用。所以一些人推測,這個UUID應該是根據裝置標識和應用標識生成唯一標識,再經過加密而來的(純推測)。
  • 官方推薦的方法是,每個應用內建立一個UUID來作為唯一標誌,並將之儲存,但是這個解決方法明顯不能接受!

缺點:

  • 你每次建立的UUID都是不一樣的,意味著,你解除安裝後重新安裝這個軟體,生成的UUID就不一樣了,無法達到我們將之作為資料分析的唯一識別符號的要求。

關於獲取UUID的程式碼:

[[UIDevice currentDevice] identifierForVendor];

不過,裝置唯一標示的問題仍然沒有解決:如果你刪除應用然後再次安裝,這個identifierForVendor的值就變了。

3.open UDID

在iOS 5釋出時,uniqueIdentifier被棄用了,這引起了廣大開發者需要尋找一個可以替代UDID,並且不受蘋果控制的方案。由此OpenUDID成為了當時使用最廣泛的開源UDID替代方案。OpenUDID在工程中實現起來非常簡單,並且還支援一系列的廣告提供商。

OpenUDID利用了一個非常巧妙的方法在不同程式間儲存標示符 — 在貼上板中用了一個特殊的名稱來儲存標示符。通過這種方法,別的程式(同樣使用了OpenUDID)知道去什麼地方獲取已經生成的標示符(而不用再生成一個新的)。而且根據貢獻者的程式碼和方法,和一些開發者的經驗,如果把使用了OpenUDID方案的應用全部都刪除,再重新獲取OpenUDID,此時的OpenUDID就跟以前的不一樣。可見,這種方法還是不保險。 
但是OpenUDID庫早已經棄用了, 在其官方的部落格中也指明瞭, 停止維護OpenUDID的原因是為了更好的向蘋果的舉措靠攏, 還指明瞭MAC Address不是一個好的選擇。

4.MAC Address

4.1.這個MAC地址是指什麼?有什麼用?

MAC(Medium/Media Access Control)地址,用來表示網際網路上每一個站點的識別符號,採用十六進位制數表示,共六個位元組(48位)。其中,前三個位元組是由IEEE的註冊管理機構 RA負責給不同廠家分配的程式碼(高位24位),也稱為“編制上唯一的識別符號” (Organizationally Unique Identifier),後三個位元組(低位24位)由各廠家自行指派給生產的介面卡介面,稱為擴充套件識別符號(唯一性)。 
MAC地址在網路上用來區分裝置的唯一性,接入網路的裝置都有一個MAC地址,他們肯定都是不同的,是唯一的。一部iPhone上可能有多個MAC地址,包括WIFI的、SIM的等,但是iTouch和iPad上就有一個WIFI的,因此只需獲取WIFI的MAC地址就好了,也就是en0的地址。 
形象的說,MAC地址就如同我們身份證上的身份證號碼,具有全球唯一性。這樣就可以非常好的標識裝置唯一性,類似與蘋果裝置的UDID號,通常的用途有: 
1)用於一些統計與分析目的,利用使用者的操作習慣和資料更好的規劃產品; 
2)作為使用者ID來唯一識別使用者,可以用遊客身份使用app又能在伺服器端儲存相應的資訊,省去使用者名稱、密碼等註冊過程。

4.2.如何使用Mac地址生成裝置的唯一標識呢?

主要分三種: 
1、直接使用“MAC Address” 
2、使用“MD5(MAC Address)” 
3、使用“MD5(Mac Address+bundle_id)”獲得“機器+應用”的唯一標識(bundle_id 是應用的唯一標識)

iOS7之前,因為Mac地址是唯一的, 一般app開發者會採取第3種方式來識別安裝對應app的裝置。為什麼會使用它?在iOS5之前,都是使用UDID的,後來被禁用。蘋果推薦使用UUID 但是也有諸多問題,從而使用MAC地址。而MAC地址跟UDID一樣,存在隱私問題,現在蘋果新發布的iOS7上,如果請求Mac地址都會返回一個固定值,那麼Mac Address+bundle_id這個值大家的裝置都變成一致的啦,跟UDID一樣相當於被禁用, 所以Mac Address 是不能夠被使用為獲取裝置唯一標識的。

5.廣告標示符(IDFA-identifierForIdentifier)

廣告識別符號,在同一個裝置上的所有App都會取到相同的值,是蘋果專門給各廣告提供商用來追蹤使用者而設的。但好在Apple預設是允許追蹤的,而且一般使用者都不知道有這麼個設定,所以基本上用來監測推廣效果,是戳戳有餘了。 
它是iOS 6中另外一個新的方法,提供了一個方法advertisingIdentifier,通過呼叫該方法會返回一個NSUUID例項,最後可以獲得一個UUID,由系統儲存著的。

#import <AdSupport/AdSupport.h>
    NSString *adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];
  • 1
  • 2

不過即使這是由系統儲存的,但是有幾種情況下,會重新生成廣告標示符。如果使用者完全重置系統((設定程式 -> 通用 -> 還原 -> 還原位置與隱私) ,這個廣告標示符會重新生成。另外如果使用者明確的還原廣告(設定程式-> 通用 -> 關於本機 -> 廣告 -> 還原廣告標示符) ,那麼廣告標示符也會重新生成。 
關於廣告標示符的還原,有一點需要注意:如果程式在後臺執行,此時使用者“還原廣告標示符”,然後再回到程式中,此時獲取廣 告標示符並不會立即獲得還原後的標示符。必須要終止程式,然後再重新啟動程式,才能獲得還原後的廣告標示符。 
所以IDFA也不可以作為獲取唯一標識的方法,來識別使用者。

6.Vendor標示符 (IDFV-identifierForVendor)

Vendor標示符,是給Vendor標識使用者用的,每個裝置在所屬同一個Vender的應用裡,都有相同的值。其中的Vender是指應用提供商,但準確點說,是通過BundleID的反轉的前兩部分進行匹配,如果相同就是同一個Vender,例如對於com.taobao.app1, com.taobao.app2 這兩個BundleID來說,就屬於同一個Vender,共享同一個IDFV的值。和IDFA不同的是,IDFV的值是一定能取到的,所以非常適合於作為內部使用者行為分析的主id,來標識使用者,替代OpenUDID。 
它是iOS 6中新增的,跟advertisingIdentifier一樣,該方法返回的是一個 NSUUID物件,可以獲得一個UUID。如果滿足條件“相同的一個程式裡面-相同的vendor-相同的裝置”,那麼獲取到的這個屬性值就不會變。如果是“相同的程式-相同的裝置-不同的vendor,或者是相同的程式-不同的裝置-無論是否相同的vendor”這樣的情況,那麼這個值是不會相同的。

    NSString *strIDFV = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
  • 1

但是如果使用者將屬於此Vender的所有App解除安裝,則IDFV的值會被重置,即再重灌此Vender的App,IDFV的值和之前不同。

7.推送token+bundle_id

推送token+bundle_id的方法: 
1、應用中增加推送用來獲取token 
2、獲取應用bundle_id 
3、根據token+bundle_id進行雜湊運算

apple push token保證裝置唯一,但必須有網路情況下才能工作,該方法並不是依賴於裝置本身,而是依賴於apple push機制,所以當蘋果push做出改變時, 你獲取所謂的唯一標識也就隨之失效了。所以此方法還是不可取的。


8. 獲取裝置唯一識別符號的推薦新方案

思路:

  • 通過呼叫CFFUUIDCreate函式來生成機器唯一識別符號UUID。但每次呼叫該函式返回的字串都不一樣,所以第一次呼叫後需把該字串儲存起來。
  • 儘管CFFUUIDCreate每次獲取的UUID會發生變化,最理想的是可以儲存在鑰匙串keychain裡面,並以此作為標識使用者裝置唯一識別符號

2.1 關於獲取UUID的官方方案

關於獲取UUID,這是官方API的建議方法:

- (NSString *) uniqueString
{
   CFUUIDRef unique = CFUUIDCreate(kCFAllocatorDefault);
   NSString *result = [(NSString *)CFUUIDCreateString(kCFAllocatorDefault, unique) autorelease];
   CFRelease(unique);
   return result;
}

2.2 基於SSKeychain的唯一識別碼方案

如上獲取的UUID,基於Git上的一個第三方庫SSKeychain,可以將UUID儲存在keychain裡面,每次呼叫先檢查鑰匙串裡面有沒有,有則使用,沒有則寫進去,保證其唯一性,

參考程式碼:


- (NSString *)getDeviceUUID
{
    
    NSString *uuidStr = [SSKeychain passwordForService:@"com.test.app1" account:@"user"];
    if (!uuidStr || [uuidStr isEqualToString:@""])
    {
        CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
        uuidStr = (__bridge NSString *)CFUUIDCreateString(kCFAllocatorDefault ,uuidRef);
        [SSKeychain setPassword:[NSString stringWithFormat:@"%@", uuidStr] forService:@"com.test.app1"account:@"user"];
    }
    return uuidStr;

}