web-dev-qa-db-fra.com

Comment conserver identifierForVendor dans ios après la désinstallation de l'application ios sur l'appareil?

Je développe une application iOS qui appelle un service Web pour la connexion. À ce moment, j'envoie les informations de connexion au serveur Web avec l'identifiant du fournisseur (identifierForVendor), afin d'identifier le périphérique uniquement pour ces informations d'authentification. Un utilisateur ne peut disposer que d'un appareil et d'un identifiant .

J'ai eu l'identifiantForVendor avec 

NSString *uuid = [[UIDevice currentDevice] identifierForVendor].UUIDString

Cet identifiant sera ensuite stocké dans la base de données du serveur Web et également dans la base de données du périphérique. La prochaine fois que l'utilisateur ouvrira une application, il tentera tout d'abord de télécharger des données à partir du serveur Web.

Un problème survient lorsque l'utilisateur désinstalle l'application et la réinstalle. J'ai constaté que l'identificateurForVendor était modifié. Donc, l'utilisateur ne peut pas aller plus loin.

Je lis la documentation Apple UIDevice Documentation

Comme mentionné ici, si toutes les applications du même fournisseur sont désinstallées du périphérique, lors de la nouvelle installation de n'importe quelle application de ce fournisseur, le nouvel identifiantForVendor sera utilisé. 

Alors, comment faire face à cela dans mon cas?

64
Harshavardhan

Vous pouvez le garder dans KeyChain

-(NSString *)getUniqueDeviceIdentifierAsString
{

 NSString *appName=[[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey];

 NSString *strApplicationUUID = [SSKeychain passwordForService:appName account:@"incoding"];
 if (strApplicationUUID == nil)
 {
    strApplicationUUID  = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    [SSKeychain setPassword:strApplicationUUID forService:appName account:@"incoding"];
 }

 return strApplicationUUID;
}
62
nerowolfe

En règle générale, n'utilisez pas identifierForVendor. Utilisez plutôt NSUUID pour générer un UUID personnalisé et le stocker dans le trousseau (car le trousseau n'est pas supprimé si l'application est supprimée et réinstallée).

19
Wain

Ajout à @ nerowolfe répondre .

SSKeychain utilise kSecAttrSynchronizableAny comme mode de synchronisation par défaut. Vous ne voulez probablement pas que identifierForVendor soit synchronisé sur plusieurs périphériques; voici donc un code:

// save identifierForVendor in keychain without sync
NSError *error = nil;
SSKeychainQuery *query = [[SSKeychainQuery alloc] init];
query.service = @"your_service";
query.account = @"your_account";
query.password = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
query.synchronizationMode = SSKeychainQuerySynchronizationModeNo;
[query save:&error];
9
griga13

Vous pouvez essayer d’utiliser KeyChain pour enregistrer votre VendorIdentifier , qui existera jusqu’à réinitialisation de votre appareil, même si vous désinstallez votre application.

5
iphonic

Version rapide

func UUID() -> String {

    let bundleName = NSBundle.mainBundle().infoDictionary!["CFBundleName"] as! String
    let accountName = "incoding"

    var applicationUUID = SAMKeychain.passwordForService(bundleName, account: accountName)

    if applicationUUID == nil {

        applicationUUID = UIDevice.currentDevice().identifierForVendor!.UUIDString

        // Save applicationUUID in keychain without synchronization
        let query = SAMKeychainQuery()
        query.service = bundleName
        query.account = accountName
        query.password = applicationUUID
        query.synchronizationMode = SAMKeychainQuerySynchronizationMode.No

        do {
            try query.save()
        } catch let error as NSError {
            print("SAMKeychainQuery Exception: \(error)")
        }
    }

    return applicationUUID
}
4
Michael Kalinin

D'accord. Je ne voulais pas utiliser un tiers - à savoir SSKeychain. C'est donc le code que j'ai essayé, assez simple et qui fonctionne bien:

    NSString *bundleId = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleIdentifier"];

KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:bundleId accessGroup:nil];
if(![keychainItem objectForKey:(__bridge id)(kSecValueData)]){
    NSString *idfa = [[[UIDevice currentDevice] identifierForVendor] UUIDString];
    [keychainItem setObject:idfa forKey:(__bridge id)(kSecValueData)];
    NSLog(@"saving item %@", [keychainItem objectForKey:(__bridge id)(kSecValueData)]);
}else{
    NSLog(@"saved item is %@", [keychainItem objectForKey:(__bridge id)(kSecValueData)]);
}
4
Gautam Jain

Il n’existe plus de moyen précis de lier un numéro unique à un périphérique. Les directives de confidentialité d’Apple ne le permettent pas.

Vous pouvez essayer de sauvegarder votre propre identifiant unique dans le trousseau, mais si l'utilisateur efface son appareil, cet identifiant disparaît également.

Généralement, c’est tout simplement faux de lier un appareil à un utilisateur }, puisque vous n’identifiez plus les utilisateurs, mais les appareils. Vous devez donc simplement modifier votre API afin que l'utilisateur puisse se reconnecter et que l'ID de fournisseur soit lié au compte de l'utilisateur. 

De plus, que se passe-t-il lorsque l'utilisateur dispose de plus d'un appareil, comme un iPhone et un iPad, et utilise votre application sur les deux? Puisque votre authentification est basée sur un identifiant unique, cela ne peut pas être fait.

2
rckoenes

J'avais utilisé KeychainAccess pod pour ce problème.

Dans votre fichier pod:

pod 'KeychainAccess', '~> 2.4' //If you are using Swift 2.3 
pod 'KeychainAccess' //Defaults to 3.0.1 which is in Swift 3

Importer le module KeychainAccess dans le fichier où vous souhaitez définir l'UUID dans le trousseau

import KeychainAccess

Utilisez le code ci-dessous pour définir et obtenir l'UUID du trousseau:

Remarque: _ ​​BundleId est la clé et UUID est la valeur

var bundleID = NSBundle.mainBundle().bundleIdentifier
    var uuidValue = UIDevice.currentDevice().identifierForVendor!.UUIDString

 //MARK: - setVenderId and getVenderId
    func setVenderId() {

        let keychain = Keychain(service: bundleID!)

        do {
            try keychain.set(venderId as String, key: bundleID!)
            print("venderId set : key \(bundleID) and value: \(venderId)")
        }
        catch let error {
            print("Could not save data in Keychain : \(error)")
        }
    }

    func getVenderId() -> String {
        let keychain = Keychain(service: bundleID!)
        let token : String = try! keychain.get(bundleID!)!
        return token
    }
0
Jayprakash Dubey