Использовать префикс идентификатора приложения Access программно

Как я могу программным образом получить доступ к строке префикса идентификатора пакета /Team ID/App ID? (Это все равно, насколько я могу судить).

Я использую оболочку связки ключей UICKeychainStore для сохранения данных в нескольких приложениях. Каждое из этих приложений имеет общую группу доступа к цепочке ключей в своих панелях прав и имеет один и тот же профиль обеспечения. По умолчанию службы keychain используют первую группу доступа в plist в качестве группы доступа для сохранения данных. Это выглядит как "AS234SDG.com.myCompany.SpecificApp", когда я отлаживаю UICKeychainStore. Я хотел бы установить группу доступа в "AS234SDG.com.myCompany.SharedStuff", но я не могу найти способ получения строки "AS234SDG" группы доступа программно и хотел бы избежать жесткого кодирования если возможно.

Ответ 1

Вы можете программным образом получить идентификатор семени Bundle, просмотрев атрибут группы доступа (т.е. kSecAttrAccessGroup) существующего элемента KeyChain. В приведенном ниже коде я ищу существующую запись KeyChain и создаю ее, если она не существует. Когда у меня есть запись KeyChain, я извлекаю из нее информацию о группе доступа и возвращаю первый компонент группы доступа, разделенный символом ".". (период) в качестве идентификатора семян Bundle.

+ (NSString *)bundleSeedID {
    NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
                           (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass,
                           @"bundleSeedID", kSecAttrAccount,
                           @"", kSecAttrService,
                           (id)kCFBooleanTrue, kSecReturnAttributes,
                           nil];
    CFDictionaryRef result = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
    if (status == errSecItemNotFound)
        status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
    if (status != errSecSuccess)
        return nil;
    NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];
    NSArray *components = [accessGroup componentsSeparatedByString:@"."];
    NSString *bundleSeedID = [[components objectEnumerator] nextObject];
    CFRelease(result);
    return bundleSeedID;
}

Ответ 2

Info.plist может иметь свою собственную информацию, и если вы пишете значение с помощью $(AppIdentifierPrefix), оно заменяется на настоящий префикс идентификатора приложения на этапе строительства.

Итак, попробуйте следующее:

В вашем Info.plist добавьте информацию о префиксе идентификатора приложения.

<key>AppIdentifierPrefix</key>
<string>$(AppIdentifierPrefix)</string>

Затем вы можете запрограммировать его программно.

NSString *appIdentifierPrefix =
    [[NSBundle mainBundle] objectForInfoDictionaryKey:@"AppIdentifierPrefix"];

Обратите внимание, что appIdentifierPrefix заканчивается периодом; например AS234SDG.

Ответ 3

Это хороший вопрос, но чтобы достичь того, что вы намеревались сделать, могло быть решение что не требует получения идентификатора семени Bundle.

Из этой статьи о той же самой оболочке связки ключей, которую вы используете:

По умолчанию будет выбрана первая группа доступа, указанная в вашем Entitlements.plist при записи и поиск по всем групп доступа, когда ни один не указан.

Затем ключ будет искать во всех группах, где предоставляется доступ. Таким образом, чтобы решить вашу проблему, вы можете добавить группу доступа всех ваших приложений пакета в свой файл permissions.plist вместо того, чтобы использовать группу "общий материал", поместите $(CFBundleIdentifier) ​​в качестве вашей первой группы ключей (ваша оболочка связки ключей будет записывать в этом группа), и вы все настроены

Ответ 4

В swift3: (на основе решения @Hiron)

Просто одна строка:

var appIdentifierPrefix = Bundle.main.infoDictionary!["AppIdentifierPrefix"] as! String

Учитывая, что в вашем Info.plist добавьте следующее свойство key-value:

: AppIdentifierPrefix

string-value: $(AppIdentifierPrefix)

Ответ 5

Вот версия Swift версии @David H:

static func bundleSeedID() -> String? {
        let queryLoad: [String: AnyObject] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: "bundleSeedID" as AnyObject,
            kSecAttrService as String: "" as AnyObject,
            kSecReturnAttributes as String: kCFBooleanTrue
        ]

        var result : AnyObject?
        var status = withUnsafeMutablePointer(to: &result) {
            SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
        }

        if status == errSecItemNotFound {
            status = withUnsafeMutablePointer(to: &result) {
                SecItemAdd(queryLoad as CFDictionary, UnsafeMutablePointer($0))
            }
        }

        if status == noErr {
            if let resultDict = result as? Dictionary<String, Any>, let accessGroup = resultDict[kSecAttrAccessGroup as String] as? String {
                let components = accessGroup.components(separatedBy: ".")
                return components.first
            }else {
                return nil
            }
        } else {
            print("Error getting bundleSeedID to Keychain")
            return nil
        }
    }