iOS獲取設備的唯一標識的方法總結以及最好的方法

我個人認為 (UUID + keychain) 的解決方法是目前最好的解決方法。

下面我列舉幾個方法做對比。

各種獲取設備唯一標識的方法介紹

一.UDID(Unique Device Identifier)

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是絕對是不能再使用了。

//UUID , 已廢除NSString*udid = [[UIDevice currentDevice] uniqueIdentifier];

1

2

為什么蘋果反對開發人員使用UDID???

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

二.UUID(Universally Unique Identifier)

UUID是Universally Unique Identifier的縮寫,中文意思是通用唯一識別碼。它是讓分布式系統中的所有元素,都能有唯一的辨識資訊,而不需要透過中央控制端來做辨識資訊的指定。這樣,每個人都可以建立不與其它人沖突的 UUID。在此情況下,就不需考慮數據庫建立時的名稱重復問題。蘋果公司建議使用UUID為應用生成唯一標識字符串。?

獲得的UUID值系統沒有存儲, 而且每次調用得到UUID,系統都會返回一個新的唯一標示符。如果你希望存儲這個標示符,那么需要自己將其存儲到NSUserDefaults, Keychain, Pasteboard或其它地方。

1.CFUUID

從iOS2.0開始,CFUUID就已經出現了。它是CoreFoundatio包的一部分,因此API屬于C語言風格。CFUUIDCreate 方法用來創建CFUUIDRef,并且可以獲得一個相應的NSString,如下代碼:

CFUUIDRef cfuuid = CFUUIDCreate(kCFAllocatorDefault);NSString*cfuuidString = (NSString*)CFBridgingRelease(CFUUIDCreateString(kCFAllocatorDefault, cfuuid));

1

獲得的這個CFUUID值系統并沒有存儲。每次調用CFUUIDCreate,系統都會返回一個新的唯一標示符。如果你希望存儲這個標示符,那么需要自己將其存儲到NSUserDefaults, Keychain, Pasteboard或其它地方。

2.NSUUID

NSUUID在iOS 6中才出現,這跟CFUUID幾乎完全一樣,只不過它是Objective-C接口。+ (id)UUID 是一個類方法,調用該方法可以獲得一個UUID。通過下面的代碼可以獲得一個UUID字符串:

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

1

跟CFUUID一樣,這個值系統也不會存儲,每次調用的時候都會獲得一個新的唯一標示符。如果要存儲的話,你需要自己存儲。在我讀取NSUUID時,注意到獲取到的這個值跟CFUUID完全一樣(不過也可能不一樣)

三.open UDID

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

OpenUDID利用了一個非常巧妙的方法在不同程序間存儲標示符 — 在粘貼板中用了一個特殊的名稱來存儲標示符。通過這種方法,別的程序(同樣使用了OpenUDID)知道去什么地方獲取已經生成的標示符(而不用再生成一個新的)。而且根據貢獻者的代碼和方法,和一些開發者的經驗,如果把使用了OpenUDID方案的應用全部都刪除,再重新獲取OpenUDID,此時的OpenUDID就跟以前的不一樣。可見,這種方法還是不保險。?

但是OpenUDID庫早已經棄用了, 在其官方的博客中也指明了, 停止維護OpenUDID的原因是為了更好的向蘋果的舉措靠攏, 還指明了MAC Address不是一個好的選擇。?

四.MAC Address

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又能在服務器端保存相應的信息,省去用戶名、密碼等注冊過程。

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 是不能夠被使用為獲取設備唯一標識的。

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

廣告標示符,在同一個設備上的所有App都會取到相同的值,是蘋果專門給各廣告提供商用來追蹤用戶而設的。但好在Apple默認是允許追蹤的,而且一般用戶都不知道有這么個設置,所以基本上用來監測推廣效果,是戳戳有余了。?

它是iOS 6中另外一個新的方法,提供了一個方法advertisingIdentifier,通過調用該方法會返回一個NSUUID實例,最后可以獲得一個UUID,由系統存儲著的。

#importNSString*adId = [[[ASIdentifierManager sharedManager] advertisingIdentifier] UUIDString];

1

2

不過即使這是由系統存儲的,但是有幾種情況下,會重新生成廣告標示符。如果用戶完全重置系統((設置程序 -> 通用 -> 還原 -> 還原位置與隱私) ,這個廣告標示符會重新生成。另外如果用戶明確的還原廣告(設置程序-> 通用 -> 關于本機 -> 廣告 -> 還原廣告標示符) ,那么廣告標示符也會重新生成。?

關于廣告標示符的還原,有一點需要注意:如果程序在后臺運行,此時用戶“還原廣告標示符”,然后再回到程序中,此時獲取廣 告標示符并不會立即獲得還原后的標示符。必須要終止程序,然后再重新啟動程序,才能獲得還原后的廣告標示符。?

所以IDFA也不可以作為獲取唯一標識的方法,來識別用戶。

六.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的值和之前不同。

七.推送token+bundle_id

推送token+bundle_id的方法:?

1、應用中增加推送用來獲取token?

2、獲取應用bundle_id?

3、根據token+bundle_id進行散列運算

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

八. NSUUID, CFUUID, IDFA, IDFV獲取的標識對比

首次運行

NSUUID:9D820D3A-4429-4918-97F7-A69588B388A4?

CFUUID:80F961D0-1E6A-4ECD-A0A9-F58ED858FE20?

IDFA:687E6A90-50A3-4424-871C-BE255D050AFD?

IDFV:8E740A99-283B-4F6A-87EF-443FB7778488

二次運行

NSUUID:23AB8D3D-4F1D-45E2-8BD7-83B451125326?

CFUUID:14DDBFCF-67A6-46B7-BB48-4EF2ADC5429F?

IDFA:687E6A90-50A3-4424-871C-BE255D050AFD?

IDFV:8E740A99-283B-4F6A-87EF-443FB7778488

卸載后, 重新安裝運行

NSUUID:BD934F9C-B7EC-4BD1-B65E-964C66537CAB?

CFUUID:29654DE0-AC93-40F9-98AB-1E10A271AF8D?

IDFA:687E6A90-50A3-4424-871C-BE255D050AFD?

IDFV:8E740A99-283B-4F6A-87EF-443FB7778488

重啟后運行

NSUUID:82711557-3A17-4B82-8F18-09AADF9DD37B?

CFUUID:FFBC73EC-CFBE-414C-870E-77C0714E0347?

IDFA:687E6A90-50A3-4424-871C-BE255D050AFD?

IDFV:8E740A99-283B-4F6A-87EF-443FB7778488

總結

說了這么多, 才發現原來沒有一種方法是可行的。沒錯, 其實自從蘋果廢除UDID后, 就不能達到獲取設備真正的唯一標識了。因為這些方法中導致獲取的唯一標示產生改變的原因, 或是重新調用方法, 或是重啟設備, 或是卸載應用, 或是還原某些標識, 或者刷新系統…?

所以, 不能達到從根本上獲取唯一標識, 我們只能做到盡可能接近。下面是我用過的方法。

如何正確的獲取設備的唯一標識

我用的方法是將獲取的UUID永久存儲在設備的KeyChain中, 這個方法在應用第一次啟動時, 將獲取的UUID存儲進KeyChain中, 每次取的時候, 檢查本地鑰匙串中有沒有, 如果沒有則需要將獲取的UUID存儲進去。當你重啟設備, 卸載應用再次安裝,都不影響, 只是當設備刷機時, KeyChain會清空, 才會消失, 才會失效。?

不只是這一種方法, 你也可以保存除UUID之外,其他合適的標識, 但利用KeyChain去存儲標識的方式應該是最接近的。

利用keyChain和UUID永久獲得設備的唯一標識

開發者可以在應用第一次啟動時調用一次,然后將該串存儲起來,以便以后替代UDID來使用。但是,如果用戶刪除該應用再次安裝時,又會生成新的字符串,所以不能保證唯一識別該設備。這就需要各路高手想出各種解決方案。所以,之前很多應用就采用MAC Address。但是現在如果用戶升級到iOS7(及其以后的蘋果系統)后,他們機子的MAC Address就是一樣的,沒辦法做區分,只能棄用此方法,重新使用UUID來標識。如果使用UUID,就要考慮應用被刪除后再重新安裝時的處理。

什么是鑰匙串?

一、在應用間利用KeyChain共享數據?

我們可以把KeyChain理解為一個Dictionary,所有數據都以key-value的形式存儲,可以對這個Dictionary進行add、update、get、delete這四個操作。對于每一個應用來說,KeyChain都有兩個訪問區,私有區和公共區。私有區是一個sandbox,本程序存儲的任何數據都對其他程序不可見。而要想在將存儲的內容放在公共區,需要先聲明公共區的名稱,官方文檔管這個名稱叫“keychain access group”,聲明的方法是新建一個plist文件,名字隨便起,內容如下:

“yourAppID.com.yourCompany.whatever”就是你要起的公共區名稱,除了whatever字段可以隨便定之外,其他的都必須如實填寫。這個文件的路徑要配置在 Project->build setting->Code Signing Entitlements里,否則公共區無效,配置好后,須用你正式的證書簽名編譯才可通過,否則xcode會彈框告訴你code signing有問題。所以,蘋果限制了你只能同公司的產品共享KeyChain數據,別的公司訪問不了你公司產品的KeyChain。

二、保存私密信息?

iOS的keychain服務提供了一種安全的保存私密信息(密碼,序列號,證書等)的方式,每個ios程序都有一個獨立的keychain存儲。相對于NSUserDefaults、文件保存等一般方式,keychain保存更為安全,而且keychain里保存的信息不會因App被刪除而丟失,所以在重裝App后,keychain里的數據還能使用。

實現代碼

首先, 我先推薦兩篇文章,里面介紹了如利用keyChain和UUID永久獲得設備的唯一標識,?Classes/KeychainItemWrapper.m和?如何使用KeyChain保存和獲取UDID?。?

然后, 再介紹下我使用的方法以及封裝的工具類, 在應用里使用使用keyChain,我們需要導入Security.framework。下面介紹下, 我在其他庫基礎上封裝的一個獲取唯一標識的工具類:

#import#importNSString *constKEY_UDID_INSTEAD = @"com.myapp.udid.test";@interfaceLZKeychain : NSObject/**

本方法是得到 UUID 后存入系統中的 keychain 的方法

不用添加 plist 文件

程序刪除后重裝,仍可以得到相同的唯一標示

但是,只有手機(設備)刷機后,系統中的鑰匙串會被清空,此時本方法失效。這種情況是我們手機(設備)所有的設置都要重新進行操作。

我個人認為 (UUID + keychain) 的解決方法是目前最好的解決方法。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容