Connect with us

Разработка

Использование on-demand ресурсов для безопасного хранения ключей API в iOS-приложениях

Следует помнить, что извлечь строки из файлов IPA довольно просто, и поэтому, если мы храним API-ключи в коде, кто-то другой может получить к ним доступ. Это, конечно, большая проблема для безопасности.

Фото аватара

Опубликовано

/

     
     

Многие приложения используют API-ключи при аутентификации сетевых запросов. Хотя есть и более эффективные способы аутентификации запросов, например OAuth с PKCE, но они не всегда возможны. Следует помнить, что извлечь строки из файлов IPA довольно просто, и поэтому, если мы храним API-ключи в коде, кто-то другой может получить к ним доступ. Это, конечно, большая проблема для безопасности. Один из способов избежать этого — использовать ресурсы Apple загружаемые по требованию с включенной предварительной загрузкой. Это означает, что как только мы установим приложение, iOS загрузит дополнительные ресурсы отдельно, и эти ресурсы могут содержать наши API-ключи. Такое разделение позволяет не помещать API-ключи в IPA-файл. Никто больше не сможет заглянуть в IPA-файл и попытаться извлечь из него строковые константы. Давайте посмотрим, как это настроить.

Первым делом мы создадим тег с поддержкой предварительной загрузки. Apple использует теги для идентификации ресурсов. Откройте настройки проекта Xcode, цель приложения, а затем вкладку Resource Tags. Добавим новый тег ресурса под названием «APIKeys».

Использование on-demand ресурсов для безопасного хранения ключей API в iOS-приложениях

Следующим шагом будет прикрепление ресурса к тегу. Мы будем использовать JSON-файл для наших API-ключей, поэтому добавьте новый JSON-файл для API-ключей. Мы просто создадим пары ключ-значение в этом файле и назначим ему тег ресурса, который можно найти в области утилит > вкладка File Inspector. В нашем примере тег имеет то же имя, что и файл «APIKeys».

Использование on-demand ресурсов для безопасного хранения ключей API в iOS-приложениях

Мы создали тег ресурса и назначали тег файлу JSON. По умолчанию тег рассматривается как ресурс по требованию и загружается только тогда, когда он требуется приложению. В случае с API-ключами имеет смысл загружать его вместе с бинарным файлом приложения, когда пользователь устанавливает это приложение. Тогда при первом запуске мы сможем сразу же сохранить API-ключ в связке ключей для дальнейшего использования. Предварительную загрузку можно включить на вкладке Resource Tags. Нажмите на кнопку Prefetched и перетащите тег APIKeys в раздел Initial Install Tags.

Использование on-demand ресурсов для безопасного хранения ключей API в iOS-приложениях

Важно отметить, что даже если мы установили этот тег как часть тегов начальной установки, все равно есть вероятность, что он будет удален. Это возможно когда пользователь устанавливает приложение, а затем долго ждет. В этом случае системе приходится загружать его снова, когда мы хотим получить к нему доступ. Поэтому код, обращающийся к тегу, может занять некоторое время. Рассмотрим простую функцию, которая получает доступ к файлу JSON через API NSBundleResourceRequest и делает ключи API доступными для приложения.

enum Constants {
  static func loadAPIKeys() async throws  {
    let request = NSBundleResourceRequest(tags: ["APIKeys"])
    try await request.beginAccessingResources()

    let url = Bundle.main.url(forResource: "APIKeys", withExtension: "json")!
    let data = try Data(contentsOf: url)
    // TODO: Store in keychain and skip NSBundleResourceRequest on next launches
    APIKeys.storage = try JSONDecoder().decode([String: String].self, from: data)

    request.endAccessingResources()
  }

  enum APIKeys {
    static fileprivate(set) var storage = [String: String]()

    static var mySecretAPIKey: String { storage["MyServiceX"] ?? "" }
    static var mySecretAPIKey2: String { storage["MyServiceY"] ?? "" }
  }
}

При такой настройке нам нужно убедиться, что функция loadAPIkeys будет вызвана до того, как мы получим доступ к mySecretAPIKey и mySecretAPIKey2. Если у нас есть централизованное место для сетевых запросов, скажем, какой-нибудь сетевой модуль, который оборачивает URLSession, то это может быть отличным местом для запуска этого асинхронного кода. Другим способом может быть задержка показа основного UI до завершения функции. Лично я бы выбрал первый вариант и интегрировал его в сетевой стек.

Пример OnDemandAPIKeyExample на GitHub.

Источник

Если вы нашли опечатку - выделите ее и нажмите Ctrl + Enter! Для связи с нами вы можете использовать info@apptractor.ru.
Advertisement

Наши партнеры:

LEGALBET

Мобильные приложения для ставок на спорт
Telegram

Популярное

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: