以编程方式检查是不是设置了密码锁

Posted

技术标签:

【中文标题】以编程方式检查是不是设置了密码锁【英文标题】:Programmatically Checking if a Passcode Lock is Set以编程方式检查是否设置了密码锁 【发布时间】:2011-09-05 16:52:07 【问题描述】:

由于我的应用会处理用户的敏感数据,我想知道是否有办法从我的应用中检查 ios 中是否设置了密码锁。

我需要检查这一点的原因是,如果用户在应用程序中有一些信息,然后将其保留在桌面上并出去几分钟。 iPad/iPhone 默认进入待机模式。如果设置了密码锁,只有输入正确的密码,任何人都可以使用 ipad。这将提供额外的安全措施,以防止任何路人查看应用程序中的敏感数据。

所以基本上,我希望我的应用程序检查密码锁是否设置,如果没有提示用户这样做。

这可能吗?

【问题讨论】:

我认为不可能。为什么不给你的应用添加一个锁定机制,这样用户就可以在不锁定整个 iPad 的情况下锁定它? 我需要的情况是当用户按住 ipad 并在紧急情况下离开一段时间或其他情况时......那个时候,ipad 会在一段时间后自动锁定(由于它的默认行为)......所以为了防止用户以外的任何人解锁ipad并查看应用程序上的敏感数据,我需要检查是否已为ipad设置密码锁,如果没有,提示用户设置密码锁... 【参考方案1】:

在 iOS 8 中,现在可以检查用户是否设置了密码。 此代码将在 iOS 7 上崩溃。

目标-C:

-(BOOL) deviceHasPasscode 
    NSData* secret = [@"Device has passcode set?" dataUsingEncoding:NSUTF8StringEncoding];
    NSDictionary *attributes = @ (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecAttrService: @"LocalDeviceServices",  (__bridge id)kSecAttrAccount: @"NoAccount", (__bridge id)kSecValueData: secret, (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly ;

    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
    if (status == errSecSuccess)  // item added okay, passcode has been set            
        SecItemDelete((__bridge CFDictionaryRef)attributes);

        return true;
    

    return false;

斯威夫特:

func deviceHasPasscode() -> Bool 
    let secret = "Device has passcode set?".dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)
    let attributes = [kSecClass as String:kSecClassGenericPassword, kSecAttrService as String:"LocalDeviceServices", kSecAttrAccount as String:"NoAccount", kSecValueData as String:secret!, kSecAttrAccessible as String:kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly]

    let status = SecItemAdd(attributes, nil)
    if status == 0 
        SecItemDelete(attributes)
        return true
    

    return false

【讨论】:

这是苹果认可的吗? 应该没问题,因为它使用的是标准钥匙串调用。【参考方案2】:

由于iOS 9,LocalAuthentication框架中有一个标志LAPolicyDeviceOwnerAuthentication

+ (BOOL)isPasscodeEnabled

    NSError *error = nil;
    LAContext *context = [[LAContext alloc] init];

    BOOL passcodeEnabled = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthentication error:&error];

    if(passcodeEnabled) 
        NSLog(@"Passcode enabled.");
        return YES;
    

    NSLog(@"Passcode NOT enabled: %@", error.localizedDescription);
    return NO;

iOS 8 以来,还有另一个标志用于检查TouchID 是否启用:

+ (BOOL)isTouchIdEnabled

    NSError *error = nil;
    LAContext *context = [[LAContext alloc] init];

    BOOL touchIDEnabled = [context canEvaluatePolicy:LAPolicyDeviceOwnerAuthenticationWithBiometrics error:&error];

    if(touchIDEnabled) 
        NSLog(@"TouchID enabled.");
        return YES;
    

    NSLog(@"TouchID NOT enabled: %@", error.localizedDescription);
    return NO;

【讨论】:

【参考方案3】:

查看The Application Runtime Environment 上的文件保护部分。文件保护要求用户启用密码锁定设置并设置有效的密码。如果您的应用程序写入/创建并归档,请使用 NSDataWritingFileProtectionComplete 选项。如果您的应用程序不使用任何文件,则创建一个虚拟文件并启用保护。

【讨论】:

如果密码锁被禁用怎么办?您仍然可以手动执行此文件保护锁定吗?我看过 wwdc 2010 关于保护应用程序数据的内容,但它假定您已打开密码锁定。您如何执行此操作? 这不再起作用了。阅读表明它至少从 iOS 5 开始就没有工作过。【参考方案4】:

适用于 iOS 8 的 Xamarin.iOS 解决方案...请注意,每次检查时我都会调用 SecKeyChain.Remove(secRecord)。我发现如果我不包括这个,我可能会让设备进入一个奇怪的状态,它试图在每次调用 SecKeyChain.Add(secRecord) 时向用户进行身份验证

private bool DetectIfPasscodeIsSet ()

    var secRecord = new SecRecord (SecKind.GenericPassword) 
        Label = "Check if passcode is set",
        Description = "Check if passcode is set",
        Account = "Check if passcode is set",
        Service = "Check if passcode is set",
        Comment = "Check if passcode is set",
        ValueData = NSData.FromString ("Check if passcode is set"),
        Generic = NSData.FromString ("Check if passcode is set")
    ;
    SecKeyChain.Remove (secRecord); 
    secRecord.AccessControl = new SecAccessControl (SecAccessible.WhenPasscodeSetThisDeviceOnly);
    var status = SecKeyChain.Add (secRecord);
    if (SecStatusCode.Success == status) 
        SecKeyChain.Remove (secRecord);
        return true;
    
    return false;

【讨论】:

谢谢。我需要这个!

以上是关于以编程方式检查是不是设置了密码锁的主要内容,如果未能解决你的问题,请参考以下文章

以编程方式删除/检查 iOS 密码

如何以编程方式使用密码设置屏幕锁定?

如何在整个时间以编程方式在 Geoserver 上设置用户名和密码

像 Touch Id 一样,是不是可以通过编程方式使用 iOS 密码锁?

如何以编程方式校准传感器,而不是手动设置 *#0*#?

以编程方式提交 WordPress 表单密码