2014-03-13 18 views
1

我有一个SGBContainer类的对象,它有一个名为objects的数组,其中包含类SGBObject的对象。目前,它们各自实施NSCoding而不是NSSecureCoding。该-initWithCoder:SGBContainer看起来是这样的:如何使用NSSecureCoding来保证集合类的内容?

- (id)initWithCoder:(NSCoder *)aCoder 
{ 
    self = [self init]; 
    if (self) 
    { 
     _objects = [aCoder decodeObjectForKey:@"objects"]; 
    } 
} 

我想切换到使用NSSecureCoding,从我所知道的,这将意味着改变上述这样:

- (id)initWithCoder:(NSCoder *)aCoder 
{ 
    self = [self init]; 
    if (self) 
    { 
     _objects = [aCoder decodeObjectOfClass:[NSArray class] forKey:@"objects"]; 
    } 
} 

...这没有太大的改进,因为数组的内容将被实例化,无论他们的类是什么。如何确保数组仅包含类SGBObject的对象而不实例化它们?

回答

3

虽然从文档中不完全清楚(而且听起来像一个奇怪的非语法方法名称),但这是-decodeObjectOfClasses:forKey:所做的。你会做类似如下:

NSSet *classes = [NSSet setWithObjects:[NSArray class], [SGBObject class], nil]; 
_objects = [aCoder decodeObjectOfClasses:classes forKey:@"objects"]; 

(信贷,这是由于:见NSSecureCoding trouble with collections of custom class

1

由于NSCoder不是收集意识,所以没有直接的方法与NSSecureCoding做到这一点。您必须手动清理阵列,以确保它仅包含SGBObject类型的对象(公平地说,这种对象可以击败NSSecureCoding的目的)。

另一种方法是自己编码和解码数组,而不是依靠NSCoder这样做。

+1

好的,谢谢。雷达,然后... http://openradar.appspot.com/16314084 – Simon

0

尝试 NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:archivedData]; unarchiver.requiresSecureCoding = YES; MyClass *myClass = [unarchiver decodeObjectOfClass:[MyClass class] forKey:@"root"]; 如果不设置unarchiver.requiresSecureCoding = YES,那么没有检查会应用。

1

Sean D.的回答是正确的,以解除阻塞的代码,但有一个警告:基础不保证数组内的类类型,如果他们是基础类。例如。下面的代码演示了此问题:

@implementation Serializable 
- (id)initWithCoder:(NSCoder *)aDecoder { 
    return [super init]; 
} 
- (void)encodeWithCoder:(NSCoder *)aCoder { 
} 
+ (BOOL)supportsSecureCoding { 
    return YES; 
} 
@end 

int main(int argc, const char * argv[]) { 

    NSArray *foo = @[ @1, @"Gotcha", [Serializable new] ]; 
    NSMutableData *archive = [NSMutableData data]; 
    NSKeyedArchiver *archiver = 
     [[NSKeyedArchiver alloc] initForWritingWithMutableData:archive]; 
    archiver.requiresSecureCoding = YES; 
    [archiver encodeObject:foo forKey:@"root"]; 
    [archiver finishEncoding]; 

    NSKeyedUnarchiver *unarchiver = 
    [[NSKeyedUnarchiver alloc] initForReadingWithData:archive]; 
    unarchiver.requiresSecureCoding = YES; 
    NSSet *classes = [NSSet setWithArray:@[ [NSArray class], [Serializable class] ]]; 
    // Should throw, but it does not. 
    NSArray *loaded = [unarchiver decodeObjectOfClasses:classes forKey:NSKeyedArchiveRootObjectKey]; 
    if (loaded.count > 2 && ![loaded[0] isKindOfClass:[Serializable class]]) { 
    NSLog(@"Successfully performed object substitution attack."); 
    NSLog(@"Class: %@", [loaded[0] class]); // All 3 objects are 
    return 1; 
    } 
    return 0; 
} 
相关问题