将唯一 ID 实现为 UUID 并将其保存在钥匙串中 [英] Implementing Unique ID as UUID and saving it in Keychain

查看:44
本文介绍了将唯一 ID 实现为 UUID 并将其保存在钥匙串中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序中需要唯一 ID,我知道,我们不能再使用 UDID,因此根据我的研究,使用 UUID 作为设备唯一 ID 并将其保存在钥匙串中将确保唯一 ID 保持不变,即使用户重新安装我的应用程序.

I need unique ID in my app and i know, we cannot use UDID anymore so as per my research, using UUID as device unique ID and saving it in keychain will ensure the unique id remain same even if user reinstalls my app.

我从 stackoverflow 上类似问题的答案之一中找到了以下代码,但是,我需要知道如何访问 keychainUtils 和 IDManager?提前感谢您的帮助.

I found the below code from one of the answer to similar question here on stackoverflow however, i need to know how to access keychainUtils and IDManager? Appreciate your help in advance.

+ (NSString *) getUniqueUUID {
    NSError * error;
    NSString * uuid = [KeychainUtils getPasswordForUsername:USER_NAME   andServiceName:SERVICE_NAME error:&error];
    if (error) {
        NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
        return nil;
    }
    if (!uuid) {
        DLog(@"No UUID found. Creating a new one.");
        uuid = [IDManager GetUUID];
        uuid = [Util md5String:uuid];
        [KeychainUtils storeUsername:kBuyassUser andPassword:uuid forServiceName:kIdOgBetilngService updateExisting:YES error:&error];
        if (error) {
            NSLog(@"Error geting unique UUID for this device! %@", [error localizedDescription]);
            return nil;
        }
    }
    return uuid;
}

推荐答案

我想提供这个作为解决方案.它不需要第三方代码.如果绝对需要,它会读取或写入 KeyChain,因此它比目前提供的解决方案更有效.此外,UUID 被写入钥匙串访问组,以便您可以在应用程序之间共享此 UUID.只需在方法开始处更改 kKeyChainVendorIDAccessGroup.

I'd like to offer this as a solution. It requires no third party code. It reads or writes to the KeyChain if it absolutely needs to, so it's more efficient that the solutions provided so far. Also, the UUID is written to a keychain access group so that you can share this UUID between your apps. Simply change kKeyChainVendorIDAccessGroup at the start of the method.

+(NSUUID *)persistentIdentifierForVendor
{
    static NSString * const kKeyChainVendorID = @"co.cwbrn.PersistentIdentifier";
    static NSString * const kKeyChainVendorIDAccessGroup = @"<AppIdentifier>.<keychain-access-group-identifier>";

    // First, check NSUserDefaults so that we're not hitting the KeyChain every single time
    NSString *uuidString = [[NSUserDefaults standardUserDefaults] stringForKey:kKeyChainVendorIDGroup];
    BOOL vendorIDMissingFromUserDefaults = (uuidString == nil || uuidString.length == 0);

    if (vendorIDMissingFromUserDefaults) {
        // Check to see if a UUID is stored in the KeyChain
        NSDictionary *query = @{
                                (__bridge id)kSecClass:             (__bridge id)kSecClassGenericPassword,
                                (__bridge id)kSecAttrAccount:       kKeyChainVendorID,
                                (__bridge id)kSecAttrService:       kKeyChainVendorID,
                                (__bridge id)kSecAttrAccessGroup:   kKeyChainVendorIDAccessGroup,
                                (__bridge id)kSecMatchLimit:        (__bridge id)kSecMatchLimitOne,
                                (__bridge id)kSecReturnAttributes:  (__bridge id)kCFBooleanTrue
                               };
        CFTypeRef attributesRef = NULL;
        OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)query, &attributesRef);
        if (result == noErr) {
            // There is a UUID, so try to retrieve it
            NSDictionary *attributes = (__bridge_transfer NSDictionary *)attributesRef;
            NSMutableDictionary *valueQuery = [NSMutableDictionary dictionaryWithDictionary:attributes];

            [valueQuery setObject:(__bridge id)kSecClassGenericPassword  forKey:(__bridge id)kSecClass];
            [valueQuery setObject:(__bridge id)kCFBooleanTrue            forKey:(__bridge id)kSecReturnData];

            CFTypeRef passwordDataRef = NULL;
            OSStatus result = SecItemCopyMatching((__bridge CFDictionaryRef)valueQuery, &passwordDataRef);
            if (result == noErr) {
                NSData *passwordData = (__bridge_transfer NSData *)passwordDataRef;
                uuidString = [[NSString alloc] initWithBytes:[passwordData bytes]
                                                      length:[passwordData length]
                                                    encoding:NSUTF8StringEncoding];
            }
        }
    }

    // Failed to read the UUID from the KeyChain, so create a new UUID and store it
    if (uuidString == nil || uuidString.length == 0) {
        // Generate the new UIID
        CFUUIDRef uuidRef = CFUUIDCreate(kCFAllocatorDefault);
        uuidString = (__bridge_transfer NSString *)CFUUIDCreateString(kCFAllocatorDefault, uuidRef);
        CFRelease(uuidRef);

        // Now store it in the KeyChain
        NSDictionary *query = @{    (__bridge id)kSecClass:             (__bridge id)kSecClassGenericPassword,
                                    (__bridge id)kSecAttrAccount:       kKeyChainVendorID,
                                    (__bridge id)kSecAttrService:       kKeyChainVendorID,
                                    (__bridge id)kSecAttrAccessGroup:   kKeyChainVendorIDAccessGroup,
                                    (__bridge id)kSecAttrLabel:         @"",
                                    (__bridge id)kSecAttrDescription:   @"",
                                    (__bridge id)kSecAttrAccessible:    (__bridge id)kSecAttrAccessibleAfterFirstUnlock,
                                    (__bridge id)kSecValueData:         [uuidString dataUsingEncoding:NSUTF8StringEncoding]
                                };

        OSStatus result = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
        if (result != noErr) {
            NSLog(@"ERROR: Couldn't add to the Keychain. Result = %ld; Query = %@", result, query);
            return nil;
        }
    }

    // Save UUID to NSUserDefaults so that we can avoid the KeyChain next time
    if (vendorIDMissingFromUserDefaults) {
        [[NSUserDefaults standardUserDefaults] setObject:uuidString forKey:kKeyChainVendorIDGroup];
    }

    return [[NSUUID alloc] initWithUUIDString:uuidString];
}

这篇关于将唯一 ID 实现为 UUID 并将其保存在钥匙串中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆