Swift защищает жестко закодированную строку для конфиденциальности [дубликат]

В следующем примере, который я написал, показано, как

  • обрабатывать асинхронные HTTP-вызовы;
  • Подождать ответа от каждого вызова API;
  • Использовать шаблон promise ;
  • Используйте шаблон Promise.All для объединения нескольких HTTP-вызовов;

Этот рабочий пример является автономным. Он будет определять простой объект запроса, который использует объект window XMLHttpRequest для совершения вызовов. Он будет определять простую функцию, чтобы дождаться завершения кучи обещаний.

Контекст. В этом примере запрашивается конечная точка Spotify Web API для поиска объектов playlist для заданного набора строк запроса:

[
 "search?type=playlist&q=%22doom%20metal%22",
 "search?type=playlist&q=Adele"
]

Для каждого элемента новый Promise запустит блок - ExecutionBlock, проанализирует результат, заплатит новый набор обещаний на основе массива результатов, который представляет собой список объектов Spotify user и выполняет новый HTTP-вызов в ExecutionProfileBlock асинхронно.

Затем вы можете увидеть вложенную структуру Promise, которая позволяет вам генерировать множественные и полностью асинхронные вложенные HTTP-вызовы и присоединять результаты к каждому подмножеству вызовов через Promise.all.

NOTE Recent Spotify search API-интерфейсам потребуется указать токен доступа в заголовках запроса:

-H "Authorization: Bearer {your access token}" 

Итак, вы должны запустить следующий пример, вам нужно поместить маркер доступа в заголовки запроса:

var spotifyAccessToken = "YourSpotifyAccessToken";
var console = {
    log: function(s) {
        document.getElementById("console").innerHTML += s + "
" } } // Simple XMLHttpRequest // based on https://davidwalsh.name/xmlhttprequest SimpleRequest = { call: function(what, response) { var request; if (window.XMLHttpRequest) { // Mozilla, Safari, ... request = new XMLHttpRequest(); } else if (window.ActiveXObject) { // Internet Explorer try { request = new ActiveXObject('Msxml2.XMLHTTP'); } catch (e) { try { request = new ActiveXObject('Microsoft.XMLHTTP'); } catch (e) {} } } // State changes request.onreadystatechange = function() { if (request.readyState === 4) { // Done if (request.status === 200) { // Complete response(request.responseText) } else response(); } } request.open('GET', what, true); request.setRequestHeader("Authorization", "Bearer " + spotifyAccessToken); request.send(null); } } //PromiseAll var promiseAll = function(items, block, done, fail) { var self = this; var promises = [], index = 0; items.forEach(function(item) { promises.push(function(item, i) { return new Promise(function(resolve, reject) { if (block) { block.apply(this, [item, index, resolve, reject]); } }); }(item, ++index)) }); Promise.all(promises).then(function AcceptHandler(results) { if (done) done(results); }, function ErrorHandler(error) { if (fail) fail(error); }); }; //promiseAll // LP: deferred execution block var ExecutionBlock = function(item, index, resolve, reject) { var url = "https://api.spotify.com/v1/" url += item; console.log( url ) SimpleRequest.call(url, function(result) { if (result) { var profileUrls = JSON.parse(result).playlists.items.map(function(item, index) { return item.owner.href; }) resolve(profileUrls); } else { reject(new Error("call error")); } }) } arr = [ "search?type=playlist&q=%22doom%20metal%22", "search?type=playlist&q=Adele" ] promiseAll(arr, function(item, index, resolve, reject) { console.log("Making request [" + index + "]") ExecutionBlock(item, index, resolve, reject); }, function(results) { // Aggregated results console.log("All profiles received " + results.length); //console.log(JSON.stringify(results[0], null, 2)); ///// promiseall again var ExecutionProfileBlock = function(item, index, resolve, reject) { SimpleRequest.call(item, function(result) { if (result) { var obj = JSON.parse(result); resolve({ name: obj.display_name, followers: obj.followers.total, url: obj.href }); } //result }) } //ExecutionProfileBlock promiseAll(results[0], function(item, index, resolve, reject) { //console.log("Making request [" + index + "] " + item) ExecutionProfileBlock(item, index, resolve, reject); }, function(results) { // aggregated results console.log("All response received " + results.length); console.log(JSON.stringify(results, null, 2)); } , function(error) { // Error console.log(error); }) ///// }, function(error) { // Error console.log(error); });

Я подробно рассмотрел это решение здесь .

20
задан TIMEX 20 April 2015 в 23:27
поделиться

4 ответа

Если вы храните его таким образом, и если кто-то посмеет с вашим приложением, он может получить доступ к вашему секретному ключу. Я бы рекомендовал вам начать хранить ваш секрет как #define или пользовательский по умолчанию (так что вы можете сначала создать свое приложение), и как только вы приблизитесь к представлению приложения, используйте keychain . Вот пример ответа

18
ответ дан Community 24 August 2018 в 19:54
поделиться

Похоже, вы используете токены доступа. Я бы использовал Keychain для доступа к токенам. Для идентификаторов клиентов я бы просто сохранил их как переменную, потому что идентификаторы клиентов не изменяются, когда токены доступа изменяются для каждого пользователя, или даже за токен обновления и брелок - это безопасное место для хранения учетных данных пользователя.

0
ответ дан Gasim 24 August 2018 в 19:54
поделиться

Я использовал объект PFConfig (словарь), который позволяет вам извлекать значения ваших приложений в переменных, хранящихся в параметрах среды сервера. Подобно переменным среды, которые могут быть получены с использованием ENV в программировании на стороне сервера, например Ruby или PHP. По-моему, это примерно так же безопасно, как использование переменных среды в Ruby или аналогичных.

PFConfig.getConfigInBackgroundWithBlock{
      (config: PFConfig?, error: NSError?) -> Void in
      if error == nil {
        if let mySecret = config["mySecret"] as? String {
          // myFunction(mySecret)
        }

    }
0
ответ дан lguerra10 24 August 2018 в 19:54
поделиться

Благодаря жесткому кодированию строки в вашем приложении злоумышленники могут расшифровать ваш двоичный файл (с помощью таких инструментов, как dumpdecrypt ) и получить строку без особых проблем (простой hexdump будет включать в себя любые строки в вашем приложении ).

Для этого существует несколько обходных решений. Вы можете реализовать конечную точку в REST API, которая вернет ваши учетные данные, которые вы могли бы вызвать при запуске. Конечно, у этого есть свои нетривиальные проблемы безопасности и требуется дополнительный HTTP-вызов. Обычно я не хотел делать это.

Другой вариант - каким-то образом запутать секретный ключ. Делая это, злоумышленники не смогут мгновенно распознать ваш ключ после дешифрования. cocoapods-keys - это один из вариантов, который использует этот метод.

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

(Также обязательно используйте HTTPS при отправке запросов, иначе это еще один хороший способ скомпрометировать ваши ключи.)

6
ответ дан Sam Symons 24 August 2018 в 19:54
поделиться
Другие вопросы по тегам:

Похожие вопросы: