iOS開發基礎149-由UUIDString引發的思考

Mr.陳發表於2024-08-09

問題1:[[UIDevice currentDevice] identifierForVendor].UUIDString什麼情況下值會變化?

[[UIDevice currentDevice] identifierForVendor].UUIDString 是一個用於標識裝置的唯一識別符號(UUID),針對同一應用程式供應商(即同一開發者的應用程式集合),在裝置上不變。然而,有一些情況會導致這個識別符號發生變化:

情況導致 identifierForVendor 變化:

  1. 應用解除安裝和重灌:當裝置上來自同一供應商的所有應用程式都被解除安裝,再重新安裝任意一個應用程式時,會生成新的 identifierForVendor。這意味著,如果使用者完全清除你的應用並重新安裝,它會獲得一個新值。

  2. 裝置恢復出廠設定:如果裝置被恢復出廠設定,也會生成新的 identifierForVendor

除此之外,identifierForVendor 不會因為裝置上的通常操作(如重啟裝置、軟體更新等)而改變。

儲存到 Keychain 的優勢

Keychain 是一個安全儲存敏感資訊的系統級服務,適用於儲存比如密碼、證書和加密金鑰等重要資料。把 identifierForVendor 儲存到 Keychain 有一些優勢:

  1. 永續性:即使使用者刪除了應用,Keychain 中儲存的資料不會被刪除。當使用者重新安裝應用時,可以從 Keychain 中恢復資料。
  2. 安全性:Keychain 提供了高安全性的儲存方式,對敏感資料的保護比普通的檔案儲存要好得多。
  3. 跨應用共享:在適當的配置下,同一供應商的應用程式可以共享 Keychain 中的資料。

下面是將 identifierForVendor 儲存到 Keychain 的示例程式碼:

#import <Security/Security.h>

- (void)storeIdentifierForVendorInKeychain {
    NSString *uuid = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    NSString *key = @"com.yourcompany.yourapp.identifierForVendor";

    // 刪除之前儲存的 UUID
    [self deleteUUIDFromKeychain:key];

    NSData *uuidData = [uuid dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *query = @{
        (id)kSecClass: (id)kSecClassGenericPassword,
        (id)kSecAttrAccount: key,
        (id)kSecValueData: uuidData,
    };

    OSStatus status = SecItemAdd((CFDictionaryRef)query, NULL);
    if (status == errSecSuccess) {
        NSLog(@"UUID stored successfully.");
    } else {
        NSLog(@"Error storing UUID: %d", (int)status);
    }
}

- (NSString *)retrieveUUIDFromKeychain {
    NSString *key = @"com.yourcompany.yourapp.identifierForVendor";

    NSDictionary *query = @{
        (id)kSecClass: (id)kSecClassGenericPassword,
        (id)kSecAttrAccount: key,
        (id)kSecReturnData: (id)kCFBooleanTrue,
    };

    CFDataRef dataRef = NULL;
    OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&dataRef);

    if (status == errSecSuccess) {
        NSData *resultData = (__bridge NSData *)dataRef;
        NSString *uuid = [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
        CFRelease(dataRef);
        return uuid;
    } else {
        NSLog(@"Error retrieving UUID: %d", (int)status);
        return nil;
    }
}

- (void)deleteUUIDFromKeychain:(NSString *)key {
    NSDictionary *query = @{
        (id)kSecClass: (id)kSecClassGenericPassword,
        (id)kSecAttrAccount: key,
    };

    OSStatus status = SecItemDelete((CFDictionaryRef)query);
    if (status == errSecSuccess) {
        NSLog(@"UUID deleted successfully.");
    } else {
        NSLog(@"Error deleting UUID: %d", (int)status);
    }
}

步驟:

  1. 儲存 UUID:使用 storeIdentifierForVendorInKeychain 方法將 identifierForVendor 儲存到 Keychain 中。
  2. 檢索 UUID:使用 retrieveUUIDFromKeychain 方法從 Keychain 中檢索儲存的 UUID。
  3. 刪除 UUID:使用 deleteUUIDFromKeychain 方法刪除儲存的 UUID。

透過這些步驟和方法,你可以確保即使應用被刪除和重新安裝,也可以從 Keychain 中恢復先前的 identifierForVendor,保持UUID的一致性。

問題2:儲存到 Keychain,什麼情況下值會變化 ?

儲存在 Keychain 中的資料通常在一些特定情況下會發生變化。以下是其中一些主要情形:

1. 恢復出廠設定

恢復出廠設定會清除裝置上的所有資料,包括應用資料、使用者檔案、系統設定和 Keychain 資料。在這種情況下,Keychain 中儲存的任何值(例如識別符號、密碼等)都會被刪除並且無法恢復。

2. 刷機

刷機通常指的是重新安裝裝置的韌體或作業系統。刷機過程也會清除裝置上的所有資料,包括 Keychain 中的資料。因此,儲存在 Keychain 中的值會被刪除。

3. 應用被解除安裝

不同於普通的檔案儲存,Keychain 中的資料在應用被解除安裝時不會被刪除。當應用重新安裝時,可以繼續訪問先前儲存的 Keychain 資料。然而,如果使用者選擇了“刪除應用的資料”或使用特定第三方工具清理 Keychain 資料,相關的儲存值可能會被刪除。

4. 裝置遷移

在某些情況下,透過 iCloud 備份或裝置遷移將 Keychain 資料同步到新裝置上。如果使用者選擇沒有遷移 Keychain 資料(例如,裝置遷移時選擇了不備份 Keychain),那麼新裝置中的值會發生變化或丟失。

5. 越獄裝置

越獄會增加 Keychain 資料被第三方工具訪問、修改或刪除的風險。儘管越獄本身不會直接改變 Keychain 中的值,但越獄後的應用和操作可能影響其資料完整性,可能導致 Keychain 資料被篡改或清除。

6. 應用自身操作

如果應用在某些條件下(如使用者登出、換新賬戶、重灌等)主動刪除或更新 Keychain 中的資料,也會導致相關值發生變化。例如:

- (void)deleteIdentifierInKeychain {
    NSString *key = @"com.yourcompany.yourapp.identifierForVendor";
    NSDictionary *query = @{
        (id)kSecClass: (id)kSecClassGenericPassword,
        (id)kSecAttrAccount: key,
    };

    OSStatus status = SecItemDelete((CFDictionaryRef)query);
    if (status == errSecSuccess) {
        NSLog(@"UUID deleted successfully.");
    } else {
        NSLog(@"Error deleting UUID: %d", (int)status);
    }
}

7. 使用者主動清除 Keychain

使用者可以透過某些工具或設定,主動選擇清除特定的 Keychain 資料,這樣會導致儲存值的刪除或變化。

常見問題:

  • 解除安裝和重新安裝應用

    • 不恢復出廠設定:重灌應用通常不會影響 Keychain 資料。
    • 恢復出廠設定或重置所有設定:Keychain 資料會被刪除。
  • 裝置切換

    • 如果使用者在裝置切換過程中未備份或恢復 Keychain 資料,新的 Keychain 資料將重新生成。

簡而言之,儘管 Keychain 儲存提供了一種相對持久的儲存機制,在以下情況下儲存值可能會發生變化或被清除:

  1. 恢復出廠設定或刷機。
  2. 裝置遷移而未同步 Keychain 資料。
  3. 越獄引起的資料篡改或清除。
  4. 應用自身操作或使用者主動清除 Keychain 資料。

相關文章