卸载应用程序时删除钥匙串项


238

我正在使用idandersen的scifihifi-iphone代码作为钥匙串并使用以下代码保存密码

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

当我从设备上删除应用程序时,密码保留在钥匙串中。

当用户从设备中删除应用程序时,我想从钥匙串中删除密码。我怎样才能做到这一点?


13
由于在删除应用程序时代码不会运行,因此您无法执行此操作。
乔纳森·格林斯潘

1
我认为您只能从应用程序内部删除钥匙串项目,而不能在卸载之前删除它。您可以查看SFHFKeychainUtils的deleteItem方法从钥匙串中删除用户名或密码。
matteodv 2011年

Answers:


406

您可以利用卸载应用程序NSUserDefaults 清除的事实。例如:

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

NSUserDefaults如果尚未设置,它将在您的应用程序首次运行时检查并设置“ FirstRun”键/值。有一条注释,您应该在其中添加代码以从钥匙串中删除值。可以调用Synchronize以确保“ FirstRun”键/值立即保留,以防用户在系统保留应用程序之前先将其手动杀死。


2
我同意Amro的观点,您可以在首次运行该应用程序时删除/清除您的钥匙串。这将清除上一次卸载该应用程序之前设置的所有内容。我对存储Facebook / Twitter凭据的其中一个应用程序执行了此操作,并且知道只有您的应用程序才能访问设置的任何钥匙串,因此它的运行状况一直很好。
XCool 2011年

感谢您的提示。
iOSAppDev 2013年

3
用户手动退出应用程序时,不会清除NSUserDefaults。synchronize在这种情况下,只会丢失已设置但系统(已定期)或尚未与磁盘同步(通过调用)的值。设置第一个运行键后,最好调用同步。是的,在重置设备(而不是从备份还原)时会清除NSUserDefaults,在这种情况下可以。
Amro 2013年

5
您错了,并且您可能正在做一些导致清除用户默认设置的操作。NSUserDefaults的全部目的是保存首选项,并使这些首选项在多次启动应用程序时保持不变。同样,重置设备或删除应用程序将删除用户默认设置。查看有多少人赞成这个答案并检查您的代码。然后阅读文档。哎呀,发给我相关的代码,我会告诉你你在做什么错。从iOS 2.0开始就是这种方式。投反对票,但我建议您先编写一个孤立的,简单的测试用例。
Amro 2013年

9
对于使用NSUserDefault,我不会很有信心。为什么?看一下该线程:stackoverflow.com/questions/20269116/…。如果您是从后台启动应用程序,则有时未设置NSUserDefaults中的自定义键。应用此答案将导致删除您的“钥匙串”自定义密钥,尽管您确实不希望这样做!
Aurelien Porte 2014年

40

对于寻找@amro答案的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")
}

*请注意,不建议使用syncnize()函数


2
if !userDefaults.bool(forKey: "hasRunBefore") {只是比较干净。
nefarianblack

1
同步调用应被删除。
Pochi

30

从设备删除应用程序后,没有触发器可以执行代码。对钥匙串的访问取决于用于对应用程序进行签名的供应配置文件。因此,没有其他应用程序能够访问钥匙串中的此信息。

当用户从设备中删除应用程序时,目的是要删除钥匙串中的密码,这无济于事,但应为您提供一些密码无法访问(仅通过重新安装原始应用程序)的便利。


因此,如果我们更改应用程序的配置文件,它将能够访问钥匙串中先前存储的值。
Moaz Saeed

27

对于那些正在寻找@amro答案的Swift版本的用户:

    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
    }

9

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

...并清除钥匙串中的记录(上面的TODO评论)

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

1
通过if (VersionTracking.IsFirstLaunchEver) {// remove keychain items}从Xamarin.Essentials 使用,您不需要的代码userDefaultsXamarin.Essentials可以为您进行包装
克里斯托弗·斯蒂芬,

7

用户卸载应用程序后,文件将从应用程序的文档目录中删除。知道了这一点,您要做的就是检查文件是否存在作为发生在其中的第一件事application:didFinishLaunchingWithOptions:。之后,无条件创建文件(即使只是一个虚拟文件)。

如果检查时文件不存在,则表明这是自最新安装以来的首次运行。如果您以后需要在应用程序中知道,请将布尔结果保存到您的应用程序委托成员中。


7

@amro的答案翻译为Swift 4.0:

if UserDefaults.standard.object(forKey: "FirstInstall") == nil {
    UserDefaults.standard.set(false, forKey: "FirstInstall")
    UserDefaults.standard.synchronize()
}

if !UserDefaults.standard.bool(forKey: "FirstInstall")如果密钥不存在,甚至默认为false。并且不需要.synchronize()。
CharlesA

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.