web-dev-qa-db-fra.com

Accéder au préfixe de l'identificateur d'application par programmation

Comment puis-je accéder au Bundle Seed ID/Team ID/App Identifier Prefix string par programmation? (Ce sont toutes la même chose pour autant que je sache).

J'utilise le wrapper de trousseau de clés UICKeychainStore pour conserver les données dans plusieurs applications. Chacune de ces applications a un groupe d'accès au trousseau partagé dans leurs listes de droits et partage le même profil d'approvisionnement. Par défaut, les services de trousseau utilisent le premier groupe d'accès du plist comme groupe d'accès dans lequel enregistrer les données. Cela ressemble à "AS234SDG.com.myCompany.SpecificApp" lorsque je débogue UICKeychainStore. Je voudrais définir le groupe d'accès sur "AS234SDG.com.myCompany.SharedStuff", mais je n'arrive pas à trouver comment obtenir la chaîne "AS234SDG" du groupe d'accès par programme et je voudrais éviter de le coder en dur si possible.

42
Jacob Jennings

Vous pouvez récupérer par programme le bundle Seed ID en regardant l'attribut de groupe d'accès (ie kSecAttrAccessGroup) d'un élément KeyChain existant. Dans le code ci-dessous, je recherche un existant Entrée KeyChain et en créer une si elle n'existe pas. Une fois que j'ai une entrée KeyChain, j'en extrait les informations du groupe d'accès et je renvoie le premier composant du groupe d'accès séparé par "." (Point) comme le Bundle Seed ID.

+ (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;
}
55
David H

Info.plist peut avoir vos propres informations et si vous écrivez une valeur avec $(AppIdentifierPrefix), elle est remplacée par le préfixe identifiant de l'application réelle lors de la phase de construction.

Alors essayez ceci:

Dans votre Info.plist, ajoutez une information sur le préfixe d'identifiant d'application.

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

Vous pouvez ensuite le récupérer par programme avec Objective-C:

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

et avec Swift:

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

Notez que appIdentifierPrefix se termine par un point; par exemple. AS234SDG.

77
Hiron

Dans Swift3: (Basé sur la solution @Hiron)

Une seule ligne:

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

Étant donné que dans votre Info.plist, ajoutez la propriété de valeur-clé suivante:

key: AppIdentifierPrefix

valeur de chaîne: $ (AppIdentifierPrefix)

6
Ronen Rabinovici

C'est une bonne question mais pour atteindre ce que vous étiez censé faire, il aurait pu y avoir une solution qui ne nécessite pas de récupérer le Bundle Seed ID.

De cette article , à propos du même wrapper de trousseau que vous utilisez:

Par défaut, il choisira le premier groupe d'accès spécifié dans votre Entitlements.plist lors de l'écriture et effectuera une recherche dans tous les groupes d'accès quand aucun n'est spécifié.

La clé sera alors recherchée dans tous les groupes où l'accès est accordé. Donc, pour résoudre votre problème, vous pouvez ajouter un groupe d'accès à toutes vos applications de bundle dans votre droit.plist au lieu d'utiliser un groupe de "trucs partagés", mettez $ (CFBundleIdentifier) ​​comme premier groupe de trousseaux (votre wrapper de trousseau écrira alors ceci groupe) et vous êtes prêt

4
Aurelien Porte

Voici la version Swift de @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? [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
        }
    }
4
balkoth