Usuń elementy pęku kluczy po odinstalowaniu aplikacji

238

Używam kodu scifihifi-iphone idandersena do pęku kluczy i zapisuję hasło za pomocą

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

Po usunięciu aplikacji z urządzenia hasło pozostaje w pęku kluczy.

Chcę usunąć hasło z pęku kluczy, gdy użytkownik usunie aplikację z urządzenia. W jaki sposób mogę to zrobić?

enc
źródło
13
Ponieważ kod nie jest uruchamiany podczas usuwania aplikacji, nie można tego zrobić.
Jonathan Grynspan
1
Myślę, że możesz usunąć element pęku kluczy tylko z wnętrza aplikacji, ale nie przed jego odinstalowaniem. Możesz rzucić okiem na metodę deleteItem SFHFKeychainUtils, aby usunąć nazwę użytkownika lub hasło z pęku kluczy.
matteodv

Odpowiedzi:

406

Możesz skorzystać z faktu, że NSUserDefaults usuwane przez odinstalowanie aplikacji. Na przykład:

- (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
}

To sprawdza i ustawia klucz / wartość „FirstRun” NSUserDefaultsprzy pierwszym uruchomieniu aplikacji, jeśli nie jest jeszcze ustawione. Jest komentarz, w którym należy umieścić kod, aby usunąć wartości z pęku kluczy. Synchronizację można wywołać, aby mieć pewność, że klucz / wartość „FirstRun” zostanie natychmiast utrwalony na wypadek, gdyby użytkownik ręcznie zabił aplikację, zanim system ją utrzyma.

Amro
źródło
2
Zgadzam się z Amro, że możesz usunąć / wyczyścić swój pęku kluczy przy pierwszym uruchomieniu aplikacji. Spowoduje to wyczyszczenie wszystkiego, co zostało ustawione przed odinstalowaniem aplikacji po raz ostatni. Zrobiłem to dla jednej z moich aplikacji, która przechowuje dane logowania na Facebooku / Twitterze i działa całkiem dobrze, wiedząc, że tylko twoja aplikacja ma dostęp do dowolnego ustawionego pęku kluczy.
XCool
Dzięki za podpowiedź.
iOSAppDev
3
Błędy NSUserDefault nie są usuwane, gdy użytkownik ręcznie zamyka aplikację. synchronizeW tym przypadku tracone są tylko wartości, które ustawiłeś, ale albo system (okresowo), albo jeszcze nie zsynchronizowałeś się z dyskiem (przez wywołanie ). Warto ustawić synchronizację połączeń po ustawieniu klucza pierwszego uruchomienia. I tak, NSUserDefaulty są usuwane, gdy urządzenie jest resetowane (i nie jest przywracane z kopii zapasowej), i w tym przypadku jest to w porządku.
Amro,
5
Mylisz się i prawdopodobnie robisz coś, co powoduje usunięcie domyślnych ustawień użytkownika. Głównym celem NSUserDefaults jest zapisywanie preferencji i utrzymywanie tych preferencji przez uruchamianie wielu aplikacji. Ponownie zresetowanie urządzenia lub usunięcie aplikacji spowoduje usunięcie domyślnych ustawień użytkownika. Spójrz, ile osób głosowało za odpowiedzią i sprawdź swój kod. Następnie przejdź do dokumentacji. Do licha, wyślij mi odpowiedni kod, a pokażę ci, co robisz źle. Tak było od iOS 2.0. Oddaj głosowanie, ale najpierw proponuję napisanie odosobnionego, prostego przypadku testowego.
Amro
9
Nie byłbym zbyt pewny korzystania z NSUserDefault w tym celu. Czemu? Spójrz na ten wątek: stackoverflow.com/questions/20269116/… . Jeśli uruchomisz aplikację z tła, są przypadki, w których klucze niestandardowe w NSUserDefaults po prostu nie są ustawione. Zastosowanie tej odpowiedzi spowoduje usunięcie niestandardowych kluczy pęku kluczy, chociaż tak naprawdę tego nie chcesz!
Aurelien Porte
40

Dla użytkowników szukających odpowiedzi @ amro w wersji Swift 3.0 :

let userDefaults = UserDefaults.standard

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

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

* Uwaga: funkcja synchronize () jest przestarzała

bwcooley
źródło
2
if !userDefaults.bool(forKey: "hasRunBefore") {To jest po prostu czystsze.
nefarianblack
1
Połączenie synchroniczne powinno zostać usunięte.
Pochi
30

Po usunięciu aplikacji z urządzenia nie ma wyzwalacza do wykonania kodu. Dostęp do pęku kluczy zależy od profilu udostępniania używanego do podpisywania aplikacji. Dlatego żadne inne aplikacje nie będą miały dostępu do tych informacji w pęku kluczy.

Nie pomaga ci to usunąć hasła z pęku kluczy, gdy użytkownik usuwa aplikację z urządzenia, ale powinno dać ci pewną wygodę, że hasło nie jest dostępne (tylko podczas ponownej instalacji oryginalnej aplikacji).

Shane Fitzgibbon
źródło
Jeśli więc zmienimy profil udostępniania naszej aplikacji, czy będzie on w stanie uzyskać dostęp do wcześniej zapisanych wartości w pęku kluczy.
Moaz Saeed,
27

Dla tych, którzy szukają szybkiej wersji odpowiedzi @ 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
źródło
9

Wersja 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();
    }

... i wyczyścić zapisy z pęku kluczy (komentarz TODO powyżej)

        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);
        }
InkwizytorJax
źródło
1
Korzystając if (VersionTracking.IsFirstLaunchEver) {// remove keychain items}z Xamarin.Essentials, nie potrzebujesz kodu do userDefaults. Xamarin.Essentials otacza to dla Ciebie .
Christopher Stephan
7

Pliki zostaną usunięte z katalogu dokumentów aplikacji, gdy użytkownik odinstaluje aplikację. Wiedząc o tym, wszystko co musisz zrobić, to sprawdzić, czy plik istnieje jako pierwsza rzecz, która się wydarzy application:didFinishLaunchingWithOptions:. Następnie bezwarunkowo utwórz plik (nawet jeśli jest to tylko plik zastępczy).

Jeśli plik nie istniał w momencie sprawdzania, wiesz, że jest to pierwsze uruchomienie od ostatniej instalacji. Jeśli chcesz się dowiedzieć później w aplikacji, zapisz wynik boolowski w elemencie delegowanym aplikacji.

Stephen
źródło
7

Odpowiedź @ amro przetłumaczona na Swift 4.0:

if UserDefaults.standard.object(forKey: "FirstInstall") == nil {
    UserDefaults.standard.set(false, forKey: "FirstInstall")
    UserDefaults.standard.synchronize()
}
Muhammad Nayab
źródło
Lub nawet if !UserDefaults.standard.bool(forKey: "FirstInstall")która domyślnie ma wartość false, jeśli klucz nie istnieje. I .synchronize () nie jest potrzebne.
CharlesA
3

Wygląda na to, że jest to domyślne zachowanie w iOS 10.3 na podstawie zachowania, którego ludzie byli świadkami w wersji beta 2. Nie znalazłem jeszcze oficjalnej dokumentacji na ten temat, więc proszę o komentarz, jeśli masz.

Stavash
źródło
7
To chyba do wersji beta 5, publiczna wersja iOS 10.3 nie zawiera tej zmiany.
Jakub Truhlář