iOS UDID與UUID

JimmyXu發表於2019-05-07

1.UDID

通用唯一識別碼 UDID(Unique Device Identifier)

是一串由40位16進位制陣列成的字串,用以標識唯一的裝置,現在想通過程式碼獲取是不可能的了,如果你想看看你裝置的UDID,可以通過iTunes來檢視。

  • 蘋果從iOS5開始就移除了通過程式碼訪問UDID的許可權,所以碼農想知道使用者裝置的UDID,是不行的。
  • 對於已越獄了的裝置,UDID並不是唯一的。使用Cydia外掛UDIDFaker,可以為每一個應用分配不同的UDID。 所以UDID作為標識唯一裝置的用途已經不大了。

關於獲取UDID的程式碼(iOS5之後已經廢掉並被AppStore封殺)

[[UIDevice currentDevice] uniqueIdentifier];

2.UUID

裝置唯一標識 UUID(Universally Unique IDentifier)

是基於iOS裝置上面某個單個的應用程式,只要使用者沒有完全刪除應用程式,則這個UUID在使用者使用該應用程式的時候一直保持不變。如果使用者刪除了這個應用程式,然後再重新安裝,那麼這個UUID已經發生了改變。

  • 同一裝置上的不同應用的UUID是互斥的,即能在改裝置上標識應用。所以一些人推測,這個UUID應該是根據裝置標識和應用標識生成唯一標識,再經過加密而來的(純推測)。
  • 官方推薦的方法是,每個應用內建立一個UUID來作為唯一標誌,並將之儲存,但是這個解決方法明顯不能接受!
  • 你每次建立的UUID都是不一樣的,意味著,你解除安裝後重新安裝這個軟體,生成的UUID就不一樣了,無法達到我們將之作為資料分析的唯一識別符號的要求。

關於獲取UUID的程式碼:

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

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

思路

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

2.1關於獲取UUID的官方方案

- (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 *)getNewUniqueIdNum{
    
    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;
}
複製程式碼

不同於上面呼叫的字串轉換(__bridge NSString *),另一種寫法:

- (NSString *)getNewUniqueIdNum{
    
    NSString *identifierNumber = [SSKeychain passwordForService:@"com.test.app1"account:@"user"];
    CFUUIDRef uuidRef = CFUUIDCreate(NULL);
    assert(uuidRef != NULL);
    CFStringRef uuidStrRef = CFUUIDCreateString(NULL, uuidRef);
    
    if (!identifierNumber){
        
        [SSKeychain setPassword: [NSString stringWithFormat:@"%@", uuidStrRef] forService:@"com.test.app1"account:@"user"];
        identifierNumber = [SSKeychain passwordForService:@"com.test.app1"account:@"user"];
    }
    return identifierNumber;
}
複製程式碼

2.3其它方案

不同於如上SSKeychain,基於一個第三方庫SAMKeyChains。SAMKeyChains對蘋果安全框架API進行了簡單封裝,支援對儲存在鑰匙串中密碼、賬戶進行訪問,包括讀取、刪除和設定。SAMKeyChains使用簡單,通過例項程式碼便可掌握。

基於SAMKeyChains方案的參考程式碼:

+ (NSString *)getDeviceId
{
    NSString * currentDeviceUUIDStr = [SAMKeychain passwordForService:@" "account:@"uuid"];
    if (currentDeviceUUIDStr == nil || [currentDeviceUUIDStr isEqualToString:@""])
    {
        NSUUID * currentDeviceUUID  =[[UIDevice currentDevice] identifierForVendor];
        currentDeviceUUIDStr = [currentDeviceUUID UUIDString];
        currentDeviceUUIDStr = [currentDeviceUUIDStr stringByReplacingOccurrencesOfString:@"-" withString:@""];
        currentDeviceUUIDStr = [currentDeviceUUIDStr lowercaseString];
        [SAMKeychain setPassword: currentDeviceUUIDStr forService:@" "account:@"uuid"];
    }
    return currentDeviceUUIDStr;
}
複製程式碼

SAMKeyChains更多詳細用法說明可以看SAMKeyChains Documentation

轉載自:iOS裝置唯一識別符號關於UDID代替方案:基於UUID和SSKeychain生成唯一識別符號新方法

相關文章