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?
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;
}
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).
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];
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.
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
}
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)]);
}
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.
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
}