[英]iOS Keychain: NSDate vs NSString
I am wondering when preparing for a Keychain item
, when would you convert NSString
to NSData
?我想知道在准备
Keychain item
时,您什么时候将NSString
转换为NSData
?
For instance: In the code provided by this tutorial http://hayageek.com/ios-keychain-tutorial/例如:在本教程提供的代码中http://hayageek.com/ios-keychain-tutorial/
It states the following:它声明如下:
[dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
However, in the book "iOS Application Security" by David Thiel used the following:但是,在 David Thiel 的“iOS 应用程序安全”一书中使用了以下内容:
[dict setObject:@"dthiel" forKey:(__bridge id)kSecAttrAccount];
So, I am quite confused, when do I need to convert NSString
to NSData
and how can I tell?所以,我很困惑,我什么时候需要将
NSString
转换为NSData
,我怎么知道?
Thank you.谢谢你。
You MUST encode the value as NSData.您必须将该值编码为 NSData。
For example:例如:
#define KeychainIdentifier @"keychain.access.identifier"
- (void)setKeyValue:(NSString *)key value:(NSString *)value {
//The keychain identifier must be encoded as `NSData`.
NSData *keychainItemID = [KeychainIdentifier dataUsingEncoding:NSUTF8StringEncoding];
//Build the query. We need to QUERY the keychain and check if the item exists.
//If it does, we will NOT be adding the item in the keychain. Note: You can "overwrite" the data if you want but for this example, I'm going to keep it simple and NOT do that.
//For this example, the item stored is a "GenericPassword".
//We will query for the existence of "one" item.
//This query will only return attributes because we are not FETCHING from the keychain. Just "checking/querying".
//Finally, the item is accessible when the device is unlocked.
NSMutableDictionary *query = [@{
(id)kSecClass : (id)kSecClassGenericPassword,
(id)kSecAttrGeneric : keychainItemID,
(id)kSecMatchLimit : (id)kSecMatchLimitOne,
(id)kSecReturnAttributes : (id)kCFBooleanTrue,
(id)kSecAttrAccessible : (id)kSecAttrAccessibleWhenUnlocked,
(id)kSecAttrAccount : key
} mutableCopy];
//Query the keychain and get all the item's attributes.
CFMutableDictionaryRef result = nil;
OSStatus error = SecItemCopyMatching((__bridge CFMutableDictionaryRef)query, (CFTypeRef *)&result);
if (error == errSecItemNotFound) {
//Item does not exist, add it to the keychain.
//To do that, we turn our query into an "INSERT".
//That means we need to remove the "return" key because we are no longer fetching/querying and returning attributes. We also have to remove the match limit.
//We also remove the match limit.
[query removeObjectForKey:(id)kSecMatchLimit];
[query removeObjectForKey:(id)kSecReturnAttributes];
//Now we encode the data to be stored in the keychain and then we submit our "INSERT" to the keychain. This will add the item in the keychain.
[query setObject:[value dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData];
error = SecItemAdd((__bridge CFMutableDictionaryRef)query, nil);
if (error == noErr) {
//Success.
}
else {
//Something went wrong.
}
}
else {
//Item already exists.
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.