Вандад Нахавандипур - iOS. Приемы программирования
Ознакомительная версия. Доступно 25 страниц из 165
Пожалуйста, внимательно изучите примечания из раздела 8.6. На данном этапе вы уже должны знать, что группа доступа, упоминаемая во всех приведенных примерах, у каждого разработчика будет называться по-своему. Обычно это командный идентификатор, генерируемый на портале Apple для разработки под iOS для каждого разработчика и обеспечивающий доступ к коду для его команды. Необходимо изменить это значение в ваших примерах и убедиться, что оно совпадает именно с вашим командным идентификатором.
Ранее был приведен код приложения, сохраняющего значения в связке ключей, расположенной в облаке iCloud. Теперь остается написать приложение, считывающее эти данные:
#import «AppDelegate.h»
#import <Security/Security.h>
@implementation AppDelegate
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
NSString *key = @"Full Name";
/* Это не ID пакета того приложения, которое записывало информацию
в связку ключей в iCloud. Это и не ID пакета данного приложения.
Идентификатор пакета данного приложения — com.pixolity.ios.cookbook.SecondSecurityApp*/
NSString *service = @"com.pixolity.ios.cookbook.SecurityApp";
NSString *accessGroup = @"F3FU372W5M.*";
NSDictionary *queryDictionary = @{
(__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
(__bridge id)kSecAttrService: service,
(__bridge id)kSecAttrAccessGroup: accessGroup,
(__bridge id)kSecAttrAccount: key,
(__bridge id)kSecReturnData: (__bridge id)kCFBooleanTrue,
(__bridge id)kSecAttrSynchronizable: (__bridge id)kCFBooleanTrue
};
CFDataRef data = NULL;
OSStatus found =
SecItemCopyMatching((__bridge CFDictionaryRef)queryDictionary,
(CFTypeRef *)&data);
if (found == errSecSuccess){
NSString *value = [[NSString alloc]
initWithData:(__bridge_transfer NSData *)data
encoding: NSUTF8StringEncoding];
NSLog(@"Value = %@", value);
} else {
NSLog(@"Failed to read the value with error = %ld", (long)found);
}
self.window = [[UIWindow alloc]
initWithFrame: [[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Необходимо отметить еще несколько деталей, связанных с работой со связкой ключей в iCloud.
• В такой связке ключей можно хранить только пароли.
• Связка ключей iCloud работает где угодно — это означает, что она появляется сразу на нескольких устройствах, принадлежащих одному пользователю iCloud. Если вы запишете элемент в связку ключей iCloud, он будет синхронизирован на всех устройствах этого пользователя. Аналогично если вы удалите элемент, то он удалится со всех устройств пользователя, связанных с iCloud. Поэтому в данном случае нужно проявлять особую осторожность.
Также следует отметить, что все остальные приемы, изученные нами в этой главе (например, обновление имеющегося элемента связки ключей — см. раздел 8.4), работают и со связкой ключей, расположенной в iCloud.
См. также
Разделы 8.0 и 8.6.
8.8. Безопасное хранение файлов в песочнице приложения
Постановка задачи
Требуется, чтобы iOS защищала файлы, расположенные в песочнице вашего приложения, от несанкционированного считывания. Такое считывание, в частности, могут выполнять файловые менеджеры для iOS, которые в изобилии встречаются в Интернете.
Решение
Сделайте следующие шаги.
1. Выполните все операции, необходимые для создания профиля инициализации приложения, — об этом см. в разделе 8.0. Приложение должно быть подключено к такому идентификатору, для которого действует защита данных (Data Protection).
2. Подпишите ваше приложение профилем инициализации.
3. Задайте разрешения на подписывание кода вашего приложения (следуйте указаниям, изложенным в разделе 8.6).
4. Используйте метод createFileAtPath: contents: attributes: экземпляра NSFileManager, чтобы сохранить ваш файл. Для свойства attributes передайте словарь, содержащий ключ NSFileProtectionKey. Этот ключ может иметь одно из следующих значений.
• NSFileProtectionNone — при таком значении сохраненный файл не имеет никакой защиты. Файл, сохраненный с таким уровнем защиты, будет доступен в приложении, сохранившем его на диск, а также любым бесплатным или коммерческим файловым менеджером, взятым из Интернета. Такая программа-менеджер может свободно просматривать файловую систему устройства с iOS, даже если это устройство защищено паролем. Указывая этот ключ, вы получаете возможность как считывать ваш файл, так и записывать в этот файл, в том числе и тогда, когда пользовательское устройство заблокировано.
• NSFileProtectionComplete — это наиболее высокий уровень защиты, который вы можете задать для ваших файлов. При наличии данного ключа приложение сможет считывать такой файл и записывать в него информацию, пока устройство разблокировано. Если устройство заблокировано, считывать файл и записывать в него какие-либо данные невозможно. При применении такого уровня защиты коммерческие файловые менеджеры не могут читать содержимое файла, даже если пользовательское устройство разблокировано.
• NSFileProtectionCompleteUnlessOpen — значение очень похоже на NSFileProtectionComplete. Разница понятна уже из названия: вы сможете получить доступ к файлу, если уже открыли его, даже если впоследствии пользователь заблокирует устройство. Итак, открыв файл впервые, вы получаете к нему гарантированный доступ до тех пор, пока существует ваше приложение.
• NSFileProtectionCompleteUntilFirstUserAuthentication — при таком значении ваше приложение сможет считывать файл и заносить в него информацию, как только пользователь в первый раз разблокирует свое устройство. После этого вы можете и далее обращаться к файлу, даже если впоследствии пользователь вновь заблокирует устройство.
Вот пример:
— (NSString *) filePath{
NSFileManager *fileManager = [[NSFileManager alloc] init];
NSError *error = nil;
NSURL *documentFolderUrl = [fileManager URLForDirectory: NSDocumentDirectory
inDomain: NSUserDomainMask
appropriateForURL: nil
create: YES
error:&error];
if (error == nil && documentFolderUrl!= nil){
NSString *fileName = @"MyFile.txt";
NSString *filePath = [documentFolderUrl.path
stringByAppendingPathComponent: fileName];
return filePath;
}
return nil;
}
— (BOOL) application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
/*
Предпосылки:
1) подписать приложение валидным профилем инициализации;
2) в вашем профиле должна быть активизирована полная защита файла;
3) добавить в проект разрешения на подписывание кода.
*/
NSFileManager *fileManager = [[NSFileManager alloc] init];
if ([self filePath]!= nil){
NSData *dataToWrite = [@"Hello, World"
dataUsingEncoding: NSUTF8StringEncoding];
NSDictionary *fileAttributes = @{
NSFileProtectionKey: NSFileProtectionComplete
};
BOOL wrote = [fileManager createFileAtPath: [self filePath]
contents: dataToWrite
attributes: fileAttributes];
if (wrote){
NSLog(@"Successfully and securely stored the file");
} else {
NSLog(@"Failed to write the file");
}
}
self.window = [[UIWindow alloc]
initWithFrame: [[UIScreen mainScreen] bounds]];
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Обсуждение
Пользователи доверяют вашим приложениям. Поэтому, когда вы запрашиваете у пользователя определенную личную информацию, например имя и фамилию, пользователь рассчитывает, что эта информация будет храниться в хорошо защищенном месте, где до нее не доберутся хакеры или кто-нибудь, кто получает временный доступ к пользовательскому устройству с iOS.
Предположим, вы пишете приложение для редактирования фотографий. Работая с этим приложением, пользователь может подключить камеру к своему устройству с iOS, импортировать свои фотографии в ваше приложение, а потом пользоваться им для редактирования, сохранения фотографий и раздачи их друзьям. Вы могли бы поступить так, как делают очень многие разработчики приложений: импортировать эти фотографии в папку Documents (Документы), где они сразу будут готовы к редактированию. Но с таким подходом связана одна проблема: любой файловый менеджер для iOS, который можно свободно скачать в Интернете, может считывать содержимое папки Documents (Документы) в любом приложении, даже если устройство заблокировано. Чтобы защитить пользовательские данные, следует активизировать защиту тех файлов, которые вы храните в песочнице приложения. Защита файлов — неотъемлемая часть безопасности пользовательского устройства, в частности, пароля к этому устройству. Допустим, пользователь установил на устройстве пароль, без которого устройство нельзя разблокировать (пусть даже этот пароль совсем простой), и такая блокировка произошла. В таком случае после того, как устройство будет заблокировано, все файлы, сохраненные в песочнице вашего приложения и обладающие ключом NSFileProtectionComplete, будут недоступны для посторонних. Прочитать такие файлы не сможет даже файловый менеджер.
Ознакомительная версия. Доступно 25 страниц из 165