我需要与 iPhone 应用程序进行简单的客户端-服务器通信,而 XML 属性列表似乎是一种非常简单的解决方案,它省去了我处理 XML 解析器委托和自己构建这些结构的麻烦。
我只是想知道将 NSPropertyListSerialization 类与外部数据一起使用是否明智?是否有任何可以利用的晦涩的 plist 功能?
是的,将 NSPropertyListSerialization 与不受信任的数据一起使用是安全的,但是在将字节包转换为 plist 类型的层次结构之后,您必须验证这些类型以确保它们与您预期的数据格式匹配。
例如,如果您希望字典具有字符串键和 NSNumbers 作为值,则必须使用以下内容进行验证:
NSString *errorDescription = nil;
NSPropertyListFormat format = 0;
id topObject = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&errorDescription];
NSDictionary *validDictionary = nil;
if ([topObject isKindOfClass:[NSDictionary class]]) {
BOOL allNumbers = YES;
for(id value in [topObject allValues]) {
allNumbers = allNumbers && [value isKindOfClass:[NSNumber class]];
}
if (allNumbers) {
validDictionary = topObject;
}
}
return validDictionary;
如果您不这样做,则数据源可能已将 plist 值放入存档中,其类型不匹配,或者可能导致您的客户端行为不端并最终成为安全漏洞的非法值。
@乔恩赫斯:谢谢。我创建了NSDictionary
类别以减少所需的isKindOfClass
es 数量。
@interface NSDictionary (TypedDictionary)
-(NSArray *)arrayForKey:(NSString*)key;
-(NSString *)stringForKey:(NSString*)key;
-(NSDictionary *)dictionaryForKey:(NSString*)key;
@end
@implementation NSDictionary (TypedDictionary)
-(NSArray *)arrayForKey:(NSString*)key {
NSArray *obj = [self objectForKey:key];
return [obj isKindOfClass:[NSArray class]] ? obj : nil;
}
-(NSString *)stringForKey:(NSString*)key {
NSString *obj = [self objectForKey:key];
return [obj isKindOfClass:[NSString class]] ? obj : nil;
}
-(NSDictionary *)dictionaryForKey:(NSString*)key {
NSDictionary *obj = [self objectForKey:key];
return [obj isKindOfClass:[NSDictionary class]] ? obj : nil;
}
@end