- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我以前从未在 App Purchase 中实现过,所以我使用了 MKStoreKit 包装器并有一个有效的实现。 MKStoreKit 将所有收据作为 BOOL 保存在 UserDefaults.plist 中,因此盗版者很容易以“破解”状态分发应用内购买。完成首次购买后,即可分发 bundle 并重新创建 .plist 以启用 IAP 解锁。
我想扩展 MKStoreKit 以在 iOS 钥匙串(keychain)中创建应用内购买验证数据。是否有任何缺点或可能的原因导致付费用户失败、不可靠或任何其他原因导致这样做总体上是个坏主意?我知道盗版是不可避免的,我绝对不想疏远付费用户,但我觉得 UserDefaults .plist 是一种很容易绕过的方法。
在我的场景中,购买时会将一个简单的字符串放入钥匙串(keychain)中。这样,如果二进制文件得到分发,则尚未启用可解锁项。当然,有可能想出一个解决方法,但需要付出更多的努力,并且知道如何找到 TRUE/FALSE 标志并使其始终返回正确的值。通过混淆,我什至可以让追踪它变得稍微困难一些。
感谢您的所有见解,我很欣赏避免强制性不可避免的盗版、处理它的回复的答案。我对这个解决方案的技术可行性更感兴趣。
最佳答案
我们在我们的应用程序中正是这样做的,并且效果很好。这是一个免费的应用程序,您可以升级到完整版本,我们将升级指示器存储在钥匙串(keychain)中。升级指示符是您选择的任意字符串,但出于钥匙串(keychain)的目的,它被视为密码,即 kSecValueData 的值在钥匙串(keychain)中加密。这种方法的一个好处是,如果用户删除应用程序然后重新安装它,一切都会像魔术一样重新启用,因为钥匙串(keychain)项目与应用程序分开存储。在用户默认值中存储一些东西的额外工作很少,我们认为这是值得的。
创建安全项的方法如下:
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);
以下是查找安全项目以检查其值(value)的方法:
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,则 key 不存在,因此您可以假设升级不存在,或者,我们所做的,放入一个表示未升级的值。
更新
添加了 kSecReturnData(感谢@Luis 指出)
关于iphone - 在应用程序钥匙串(keychain)中存储 In App Purchase 收据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4978852/
我正在尝试创建一个程序,其中字符串的前三个字符重复给定次数,如下所示: foo('Chocolate', 3) # => 'ChoChoCho' foo('Abc', 3) # => 'AbcAbcA
我有以下字符串: std::string str = "Mode:AAA:val:101:id:A1"; 我想分离一个位于 "val:" 和 ":id" 之间的子字符串,这是我的方法: std::st
DNA 字符串可以是任意长度,包含 5 个字母(A、T、G、C、N)的任意组合。 压缩包含 5 个字母(A、T、G、C、N)的 DNA 字母串的有效方法是什么?不是考虑每个字母表 3 位,我们可以使用
是否有一种使用 levenstein 距离将一个特定字符串与第二个较长字符串中的任何区域进行匹配的好方法? 例子: str1='aaaaa' str2='bbbbbbaabaabbbb' if str
使用 OAuth 并使用以下函数使用我们称为“foo”(实际上是 OAuth token )的字符串加密 key public function encrypt( $text ) { // a
我是一名优秀的程序员,十分优秀!