我正在学习NSSecureCodingApple在iOS 6中引入的协议.
根据我的理解,到目前为止,只要一个类对自身的实例进行编码/解码,就应该使用它,以防止替换攻击.
我想知道在其他情况下使用它是否合适.
具体来说,如果一个类NSCoding通过编码/解码其实例变量来符合,而不是整个实例,那么它仍然是可行的NSSecureCoding吗?
假设我有一个实现NSCoding如下的类
- (void)encodeWithCoder:(NSCoder *)encoder {
[encoder encodeObject:self.aString forKey:@"aMeaningfulString"];
}
- (id)initWithCoder:(NSCoder *)decoder {
if((self = [super init])) {
self.aString = [decoder decodeObjectForKey:@"aMeaningfulString"];
}
return self;
}
Run Code Online (Sandbox Code Playgroud)
并且还假设没有涉及XPC.此类的实例将存储在磁盘上的plist中.
在安全方面,使用是否有任何好处,-decodeObjectOfClass:forKey:而不是
-decodeObjectForKey:?
我想在UNMutableNotificationContent的userinfo中使用cutom对象,但它不起作用.当我在userinfo中放置自定义对象时,不会触发通知.
使用此代码,会触发通知:
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
content.categoryIdentifier = "alarmNotificationCategory"
content.sound = UNNotificationSound.default()
content.userInfo = ["myKey": "myValue"] as [String : Any]
let request = UNNotificationRequest(identifier: "alarmNotification", content: content, trigger: nil)
UNUserNotificationCenter.current().add(request) { error in
UNUserNotificationCenter.current().delegate = self
if error != nil {
print(error!)
}
}
Run Code Online (Sandbox Code Playgroud)
使用以下内容,不会发出错误,但不会触发通知:
let content = UNMutableNotificationContent()
content.title = "title"
content.body = "body"
content.categoryIdentifier = "alarmNotificationCategory"
content.sound = UNNotificationSound.default()
content.userInfo = ["myKey": TestClass(progress: 2)] as [String : Any]
let request = UNNotificationRequest(identifier: …Run Code Online (Sandbox Code Playgroud) 在 iOS 12 中,Apple 引入了NSSecureUnarchiveFromDataTransformerName用于 CoreData 模型实体的可转换属性。我曾经将 Transformer Name 字段保持为空,它隐式使用了NSKeyedUnarchiveFromDataTransformerName. 这个转换器现在已被弃用,将来保持该字段为空将意味着NSSecureUnarchiveFromDataTransformerName取而代之。
在 iOS 13 中,如果该字段为空,您现在会收到一个运行时警告,告诉您上述内容。我在任何地方都找不到关于此的任何文档,我得到的唯一参考是 WWDC 2018 核心数据最佳实践演讲,其中简要提到了我刚才所说的内容。
现在我有一个带有实体的模型,该实体直接将HTTPURLResponse对象存储在 Transformable 属性中。它符合NSSecureCoding,我在运行时检查supportsSecureCoding是true。
NSSecureUnarchiveFromDataTransformerNameTransformer Name 的设置崩溃并显示以下消息:
Object of class NSHTTPURLResponse is not among allowed top level class list (
NSArray,
NSDictionary,
NSSet,
NSString,
NSNumber,
NSDate,
NSData,
NSURL,
NSUUID,
NSNull
) with userInfo of (null)
Run Code Online (Sandbox Code Playgroud)
所以听起来 Transformable 属性只能是这些顶级对象。
我尝试对安全转换器进行子类化并allowedTopLevelClasses按照文档的建议覆盖该属性:
@available(iOS 12.0, *)
public class NSSecureUnarchiveHTTPURLResponseFromDataTransformer: NSSecureUnarchiveFromDataTransformer …Run Code Online (Sandbox Code Playgroud) 我决定使用NSSecureCoding它NSCoding,但我无法让它工作.
我希望以下代码失败,因为我正在编码NSString但尝试解码NSNumber.但是,初始化对象时不会抛出异常.
+ (BOOL)supportsSecureCoding
{
return YES;
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
// prints '1' as expected
NSLog(@"%d", coder.requiresSecureCoding);
// unexpectedly prints 'foo' (expecting crash)
NSLog(@"%@", [coder decodeObjectOfClass:NSNumber.class forKey:@"bar"]);
return [super init];
}
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:@"foo" forKey:@"bar"];
}
Run Code Online (Sandbox Code Playgroud)
这是我用来测试上面代码片段的代码:
MyClass *object = [[MyClass alloc] init];
NSMutableData *const data = [[NSMutableData alloc] init];
NSKeyedArchiver *const archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
archiver.requiresSecureCoding = YES;
[archiver encodeObject:object forKey:@"root"];
[archiver finishEncoding];
NSKeyedUnarchiver *const …Run Code Online (Sandbox Code Playgroud) 我花了整个下午的时间撞到墙上,试图弄清楚为什么这门课的解码失败了.该类有一个属性,它是Foo对象的NSArray.Foo符合NSSecureCoding,我已成功编码并解码了该类.我在initWithCoder中收到错误:表示无法解码类Foo.通过一些实验,我发现我需要将[Foo类]添加到initWithCoder:为了使它工作.也许这会帮助那些遇到同样问题的人.我的问题是,为什么这是必要的?我没有发现在Apple的文档中这是必要的.
#import "Foo.h"
@interface MyClass : NSObject <NSSecureCoding>
@property (nonatomic) NSArray *bunchOfFoos;
@end
@implementation MyClass
static NSString *kKeyFoo = @"kKeyFoo";
+ (BOOL) supportsSecureCoding
{
return YES;
}
- (void) encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:self.bunchOfFoos forKey:kKeyFoo];
}
- (id) initWithCoder:(NSCoder *)decoder
{
if (self = [super init])
{
[Foo class]; // Without this, decoding fails
_bunchOfFoos = [decoder decodeObjectOfClass:[NSArray class] forKey:kKeyFoo];
}
return self;
}
@end
Run Code Online (Sandbox Code Playgroud) 我正在创建一个链表并使用容器对对象,下一个和以前的属性进行分组.像基金会收藏品一样,我希望它能够实施NSSecureCoding.这是宣言:
@interface ListContainer : NSObject <NSCopying, NSSecureCoding>
@property (readonly, nonatomic) id object;
@property (nonatomic) ListContainer * next;
@property (nonatomic) ListContainer * previous;
@end
Run Code Online (Sandbox Code Playgroud)
当实现该- initWithCoder:方法时,它让我觉得我不知道该对象使用什么类:
- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
_object = [aDecoder decodeObjectOfClass:<#(__unsafe_unretained Class)#> forKey:@"object"];
BOOL nextIsNil = [aDecoder decodeBoolForKey:@"nextIsNil"];
if (!nextIsNil) {
// Decode next
_next = [aDecoder decodeObjectOfClass:[ListContainer class] forKey:@"next"];
if (_next == nil) {
return nil;
}
// Link the nodes manually to prevent infinite recursion …Run Code Online (Sandbox Code Playgroud) 我在采用NSSecureCoding方面遇到了麻烦.我编码一个包含我的自定义类的对象的数组,它NSSecureCoding正确采用.当我解码它,传递类NSArray(它是我编码的对象的类)时,它会抛出异常.但是,当使用字符串数组执行完全相同的操作时,它可以正常工作.我没看到我的类和NSString之间有什么区别.
#import <Foundation/Foundation.h>
@interface Foo : NSObject <NSSecureCoding>
@end
@implementation Foo
- (id)initWithCoder:(NSCoder *)aDecoder {
return [super init];
}
- (void)encodeWithCoder:(NSCoder *)aCoder {
}
+ (BOOL)supportsSecureCoding {
return YES;
}
@end
int main() {
@autoreleasepool {
NSMutableData* data = [[NSMutableData alloc] init];
NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:@[[Foo new]] forKey:@"foo"];
[archiver encodeObject:@[@"bar"] forKey:@"bar"];
[archiver finishEncoding];
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
unarchiver.requiresSecureCoding = YES;
// throws exception: 'value for key 'NS.objects' was …Run Code Online (Sandbox Code Playgroud) 我目前正在尝试iOS 10 Beta并决定将我的Swift代码转换为Swift 3.到现在为止,我能够安全地解码一个String
coder.decodeObjectOfClass(NSString.self, forKey: CoderKeys.code) as! String
Run Code Online (Sandbox Code Playgroud)
转换到Swift 3后,Xcode给了我以下错误:
'decodeObjectOfClass(_:forKey:)' is unavailable in Swift: use generic 'decodeObjectClass(_:forKey:)'
Run Code Online (Sandbox Code Playgroud)
正如我所提到的,我正在使用NSSecureCoding,所以很遗憾decodeObject(forKey: String)不会这样做.这是测试版错误吗?我错过了什么?
我在创建使用 NSSecureCoding 及其子类的类时遇到问题。
class ClassA: NSObject, NSSecureCoding {
public static var supportsSecureCoding: Bool { return true }
}
class ClassB: ClassA {
public static var supportsSecureCoding: Bool { return true } // "Cannot override static var"
}
Run Code Online (Sandbox Code Playgroud)
我应该这样称呼,因为 NSObject.h 中的文档说,
此属性必须在所有允许安全编码的类上返回 YES。采用 NSSecureCoding 并覆盖 initWithCoder: 的类的子类也必须覆盖此方法并返回 YES。// 编写解码数据的方法时应参考安全编码指南。
目标-C:
@property (class, readonly) BOOL supportsSecureCoding;
Run Code Online (Sandbox Code Playgroud)
迅速:
public static var supportsSecureCoding: Bool { get }
Run Code Online (Sandbox Code Playgroud)
我正在使用 Xcode 10.0,在 Swift 4.0 和 Swift 4.2 上都尝试过。人们如何解决这个问题?任何帮助表示赞赏。
更新:使用 时public class var supportsSecureCoding,它会编译,但在使用Optimize for …
我有一个Objective-C协议,需要遵守NSSecureCoding:
@protocol MyProtocol <NSObject, NSSecureCoding>
…
@end
Run Code Online (Sandbox Code Playgroud)
我有一个父对象,该对象存储对符合标准的对象的引用MyProtocol,我希望父对象也符合NSSecureCoding。当我尝试这个:
required init?(coder aDecoder: NSCoder) {
if let childObject = aDecoder.decodeObject(of: MyProtocol.self, forKey: "childObject") {
self. childObject = childObject
} else {
return nil
}
}
Run Code Online (Sandbox Code Playgroud)
我收到错误:'decodeObject(of:forKey:)' is unavailable in Swift: use generic 'decodeObjectOfClass(_:forKey:)'。
如果您不知道所编码对象的特定类,是否可以使用NSSecureCoding?
我有一个class对象,该对象SGBContainer具有一个名为class 的数组objects,其中包含class对象SGBObject。当前,它们各自实现NSCoding,但不实现NSSecureCoding。在-initWithCoder:为SGBContainer这个样子的:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [self init];
if (self)
{
_objects = [aCoder decodeObjectForKey:@"objects"];
}
}
Run Code Online (Sandbox Code Playgroud)
我想切换为使用NSSecureCoding,据我所知,这意味着将上述内容更改为:
- (id)initWithCoder:(NSCoder *)aCoder
{
self = [self init];
if (self)
{
_objects = [aCoder decodeObjectOfClass:[NSArray class] forKey:@"objects"];
}
}
Run Code Online (Sandbox Code Playgroud)
...没有太大的改进,因为无论其类如何,数组的内容都会被实例化。如何确保数组仅包含类对象SGBObject而不实例化它们?
我了解使用“NSSecureCoding”可以安全地将数据存储到磁盘,类似于钥匙串作为安全存储信息的地方。
我还了解钥匙串具有在同一提供商的应用程序之间共享的优势。如果人们忽略钥匙串共享功能,是否可以说,与 NSSecureCoding 相比,将数据存储在钥匙串中同样安全?
我有一个用户对象
class User: NSObject, NSSecureCoding {
private enum CodingKeys: String, CodingKey {
case test
}
public static var supportsSecureCoding: Bool {
return true
}
override init() {}
var test: String = "teeees"
func encode(with aCoder: NSCoder) {
aCoder.encode(self.test as NSString)
}
required init?(coder aDecoder: NSCoder) {
test = aDecoder.decodeObject(of: NSString.self, forKey: CodingKeys.test.rawValue)! as String
}
}
Run Code Online (Sandbox Code Playgroud)
我存档的
let user = User()
let data = NSKeyedArchiver.archivedData(withRootObject: user)
try! data.write(to: DocumentHelper.cashURLForID(id: "TTYYUU"))
Run Code Online (Sandbox Code Playgroud)
TTYYUU的内容是:
6270 6c69 7374 3030 d401 …