Supprimer les éléments du trousseau lorsqu'une application est désinstallée

238

J'utilise scifihifi-iphone de idandersen code pour porte - clés et enregistrer le mot de passe à l' aide

[SFHFKeychainUtils storeUsername:@"User" andPassword:@"123"
              forServiceName:@"TestService" updateExisting:YES error:&error];

Lorsque je supprime l'application de l'appareil, le mot de passe reste dans le trousseau.

Je souhaite supprimer le mot de passe du trousseau lorsque l'utilisateur supprime l'application de l'appareil. Comment puis-je faire ceci?

enc
la source
13
Étant donné que votre code ne s'exécute pas lorsque votre application est supprimée, vous n'avez aucun moyen de le faire.
Jonathan Grynspan
1
Je pense que vous pouvez supprimer un élément de trousseau uniquement depuis l'intérieur de l'application, mais pas avant de le désinstaller. Vous pouvez consulter la méthode deleteItem de SFHFKeychainUtils pour supprimer un nom d'utilisateur ou un mot de passe du trousseau.
matteodv

Réponses:

406

Vous pouvez profiter du fait qu'ils NSUserDefaults sont effacés par la désinstallation d'une application. Par exemple:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    //Clear keychain on first run in case of reinstallation
    if (![[NSUserDefaults standardUserDefaults] objectForKey:@"FirstRun"]) {
        // Delete values from keychain here
        [[NSUserDefaults standardUserDefaults] setValue:@"1strun" forKey:@"FirstRun"];
        [[NSUserDefaults standardUserDefaults] synchronize];
    }

    //...Other stuff that usually happens in didFinishLaunching
}

Cela vérifie et définit une clé / valeur "FirstRun" lors NSUserDefaultsde la première exécution de votre application si elle n'est pas déjà définie. Il y a un commentaire où vous devez mettre du code pour supprimer des valeurs du trousseau. Synchronize peut être appelé pour s'assurer que la clé / valeur "FirstRun" est immédiatement conservée au cas où l'utilisateur tue l'application manuellement avant que le système ne la persiste.

Amro
la source
2
Je suis d'accord avec Amro que vous pouvez supprimer / purger votre trousseau lors de la première exécution de l'application. Cela effacera tout ce qui a été défini avant la dernière désinstallation de l'application. J'ai fait cela pour l'une de mes applications qui stocke les informations d'identification Facebook / Twitter et cela fonctionne assez bien en sachant que seule votre application a accès à n'importe quel trousseau qui a été défini.
XCool
Merci pour cet indice.
iOSAppDev
3
NSUserDefaults ne sont pas effacés lorsque l'utilisateur quitte manuellement l'application. Seules les valeurs que vous avez définies mais soit le système (périodiquement), soit vous n'avez pas encore synchronisé avec le disque (en appelant synchronize) sont perdues dans ce cas. C'est une bonne idée d'appeler synchronize après avoir défini la première clé d'exécution. Et oui, NSUserDefaults sont effacés lorsqu'un périphérique est réinitialisé (et non restauré à partir de la sauvegarde), et c'est bien dans ce cas.
Amro
5
Vous vous trompez et vous faites probablement quelque chose qui provoque la suppression des valeurs par défaut des utilisateurs. L'intérêt de NSUserDefaults est de sauvegarder les préférences et de les faire persister lors de plusieurs lancements d'applications. Encore une fois, la réinitialisation de l'appareil ou la suppression d'une application supprimera les valeurs par défaut de l'utilisateur. Regardez combien de personnes ont voté pour cette réponse et vérifiez votre code. Allez ensuite lire la documentation. Heck, envoyez-moi le code correspondant et je vais vous montrer ce que vous faites mal. C'est ainsi depuis iOS 2.0. Votez contre, mais je suggérerais d'abord d'écrire un cas de test isolé et simple.
Amro
9
Je ne serais pas très confiant sur l'utilisation de NSUserDefault pour cela. Pourquoi? Jetez un œil à ce fil: stackoverflow.com/questions/20269116/… . Si vous démarrez votre application en arrière-plan, il y a des cas où vos clés personnalisées dans NSUserDefaults ne sont tout simplement pas définies. L'application de cette réponse entraînerait la suppression de vos clés personnalisées de trousseau, bien que vous ne vouliez vraiment pas cela!
Aurelien Porte
40

Pour les utilisateurs à la recherche d'une version Swift 3.0 de la réponse de @ amro:

let userDefaults = UserDefaults.standard

if !userDefaults.bool(forKey: "hasRunBefore") {
     // Remove Keychain items here

     // Update the flag indicator
     userDefaults.set(true, forKey: "hasRunBefore")
}

* notez que la fonction synchronize () est déconseillée

bwcooley
la source
2
if !userDefaults.bool(forKey: "hasRunBefore") {C'est juste plus propre.
nefarianblack
1
L'appel de synchronisation doit être supprimé.
Pochi
30

Il n'y a pas de déclencheur pour exécuter du code lorsque l'application est supprimée de l'appareil. L'accès au trousseau dépend du profil d'approvisionnement utilisé pour signer l'application. Par conséquent, aucune autre application ne pourrait accéder à ces informations dans le trousseau.

Cela ne vous aide pas à supprimer le mot de passe dans le trousseau lorsque l'utilisateur supprime l'application de l'appareil, mais cela devrait vous rassurer que le mot de passe n'est pas accessible (uniquement à partir d'une réinstallation de l'application d'origine).

Shane Fitzgibbon
la source
Donc, si nous modifions le profil d'approvisionnement de notre application, serait-il en mesure d'accéder aux valeurs précédemment stockées dans le trousseau.
Moaz Saeed
27

Pour ceux qui recherchent une version Swift de la réponse de @ amro:

    let userDefaults = NSUserDefaults.standardUserDefaults()

    if userDefaults.boolForKey("hasRunBefore") == false {

        // remove keychain items here


        // update the flag indicator
        userDefaults.setBool(true, forKey: "hasRunBefore")
        userDefaults.synchronize() // forces the app to update the NSUserDefaults

        return
    }
rsc
la source
9

Version C # Xamarin

    const string FIRST_RUN = "hasRunBefore";
    var userDefaults = NSUserDefaults.StandardUserDefaults;
    if (!userDefaults.BoolForKey(FIRST_RUN))
    {
        //TODO: remove keychain items
        userDefaults.SetBool(true, FIRST_RUN);
        userDefaults.Synchronize();
    }

... et pour effacer les enregistrements du trousseau (commentaire TODO ci-dessus)

        var securityRecords = new[] { SecKind.GenericPassword,
                                    SecKind.Certificate,
                                    SecKind.Identity,
                                    SecKind.InternetPassword,
                                    SecKind.Key
                                };
        foreach (var recordKind in securityRecords)
        {
            SecRecord query = new SecRecord(recordKind);
            SecKeyChain.Remove(query);
        }
InquisitorJax
la source
1
En utilisant à if (VersionTracking.IsFirstLaunchEver) {// remove keychain items}partir de Xamarin.Essentials, vous n'avez pas besoin du code pour le userDefaults. Xamarin.Essentials enveloppe cela pour vous .
Christopher Stephan
7

Les fichiers seront supprimés du répertoire de documents de votre application lorsque l'utilisateur désinstallera l'application. Sachant cela, tout ce que vous avez à faire est de vérifier si un fichier existe en premier application:didFinishLaunchingWithOptions:. Ensuite, créez inconditionnellement le fichier (même s'il ne s'agit que d'un fichier factice).

Si le fichier n'existait pas au moment de la vérification, vous savez qu'il s'agit de la première exécution depuis la dernière installation. Si vous devez le savoir ultérieurement dans l'application, enregistrez le résultat booléen dans le membre délégué de votre application.

Stephen
la source
7

@ amro a traduit sa réponse en Swift 4.0:

if UserDefaults.standard.object(forKey: "FirstInstall") == nil {
    UserDefaults.standard.set(false, forKey: "FirstInstall")
    UserDefaults.standard.synchronize()
}
Muhammad Nayab
la source
Ou même par if !UserDefaults.standard.bool(forKey: "FirstInstall")défaut à false si la clé n'existe pas. Et .synchronize () n'est pas nécessaire.
CharlesA
3

Cela semble être le comportement par défaut sur iOS 10.3 basé sur le comportement que les gens ont observé en version bêta # 2. Je n'ai pas encore trouvé de documentation officielle à ce sujet, veuillez commenter si vous en avez.

Stavash
la source
7
C'était jusqu'à la version bêta 5, je suppose, la version publique d'iOS 10.3 ne contient pas ce changement.
Jakub Truhlář