首页 文章

在应用程序购买收据中存储应用程序Keychain

提问于
浏览
42

我之前从未实现过In App Purchase,所以我使用了MKStoreKit包装器,并且有一个可行的实现 . MKStoreKit将所有收据保存在UserDefaults .plist中作为BOOL,因此盗版者在“破解”状态下分发应用内购买非常简单 . 完成第一次购买后,可以分发捆绑包,并可以重新创建.plist以启用IAP解锁 .

我想扩展MKStoreKit以在iOS钥匙串中创建In App Purchase验证数据 . 是否有任何缺点或可能的原因导致付费用户失败,不可靠或任何其他原因导致这样做总体上是个坏主意?我知道盗版是不可避免的,我绝对不想疏远付费用户,但我觉得UserDefaults .plist太容易绕过了 .

在我的场景中,购买时会将一个简单的字符串放入钥匙串中 . 这样,如果二进制文件已分发,则尚未启用解锁 . 当然,有可能提出一种解决方法,但需要花费更多精力并知道如何找到TRUE / FALSE标志并使其始终返回正确的值 . 通过模糊处理,我甚至可以使跟踪它变得更加困难 .

感谢您的所有见解,我感谢答案,避免强制性的不可避免的盗版,处理它的回复 . 我对这个解决方案的技术可行性更感兴趣 .

1 回答

  • 54

    我们在我们的应用程序中做到了这一点并且效果很好 . 这是一个免费的应用程序,您可以升级到完整版本,我们将升级指标存储在钥匙串中 . 升级指示符是您选择的任意字符串,但出于密钥链的目的,它被视为密码,即kSecValueData的值在密钥链中被加密 . 关于这种方法的一个很好的好处是,如果用户删除应用程序然后重新安装它,所有内容都会像魔术一样重新启用,因为钥匙串项目与应用程序分开存储 . 而且,在用户默认值中存储某些东西的额外工作很少,我们认为这是值得的 .

    以下是创建安全项的方法:

    NSMutableDictionary* dict = [NSMutableDictionary dictionary];
    
    [dict setObject: (id) kSecClassGenericPassword  forKey: (id) kSecClass];
    [dict setObject: kYourUpgradeStateKey           forKey: (id) kSecAttrService];
    [dict setObject: kYourUpgradeStateValue         forKey: (id) kSecValueData];
    
    SecItemAdd ((CFDictionaryRef) dict, NULL);
    

    以下是查找安全项以检查其值的方法:

    NSMutableDictionary* query = [NSMutableDictionary dictionary];
    
    [query setObject: (id) kSecClassGenericPassword forKey: (id) kSecClass];
    [query setObject: kYourUpgradeStateKey          forKey: (id) kSecAttrService];
    [query setObject: (id) kCFBooleanTrue           forKey: (id) kSecReturnData];
    
    NSData* upgradeItemData = nil;
    SecItemCopyMatching ( (CFDictionaryRef) query, (CFTypeRef*) &upgradeItemData );
    if ( !upgradeItemData )
    {
        // Disable feature
    }
    else
    {
        NSString* s = [[[NSString alloc] 
                            initWithData: upgradeItemData 
                                encoding: NSUTF8StringEncoding] autorelease];
    
        if ( [s isEqualToString: kYourUpgradeStateValue] )
        {
            // Enable feature
        }
    }
    

    如果upgradeItemData为nil,则该密钥不存在,因此您可以假设升级不存在,或者我们所做的是放入一个意味着未升级的值 .

    Update

    添加了kSecReturnData(感谢@Luis指出)

    Code on GitHub (ARC variant)

相关问题