Автоинкрементные идентификаторы: раздача своих данных

Учебные руководства и значения по умолчанию в ORM системах нам всегда говорят, что каждая таблица SQL должна иметь автоинкрементный ID. Это странная общая ошибка старых и новых «туториалов» в различных формах. Почему автоинкрементные идентификаторы представляют проблему? Потому, что это означает, что люди могут скачать вашу базу данных.

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

Социологическое исследование

Я заключил контракт на стартап, проходящий через акселератор, где одна из команд создавала уникальную базу данных сгенерированных пользователями фотографий, и эти фотографии были произведениями искусства. Такие произведения, как удивительное граффити, неизвестные установки и т.д., недоступные больше нигде в интернете.

У них были следующие два URL адреса в их API:

  1. GET /artworks/234
  2. GET /users/6138

Какие проблемы здесь?

Утечка «успеха» к конкурентам

Как стартап, у вас есть конкуренты. Разрешение конкурентам узнать размер вашего набора данных, и сколько пользователей вы имеете в своей системе, могло бы привести к некоторым довольно неловким ситуациям.

Глядя на URL GET /users/6138, я могу перейти на GET /users/1. Если мне покажутся данные, то я могу обоснованно предположить, что у них есть, по крайней мере, 6 138 пользователей, а общее количество я смогу легко найти, написав скрипт, который инкрементирует идентификатор и считает каждый HTTP 200 статус, а также учитывает такие статусы как 404 или 410, для предоставления точного числа активных пользователей и сколько закрыло свои аккаунты.

Это могло бы смутить большую компанию или, по крайней мере, уничтожить маленький стартап.

Утечка данных конкурентам (или придуркам)

Утечка статистики к вашим врагам не может быть чем-то таким, чтобы удержало вас в ночное время, но что насчёт раздачи ваших фактических данных?

В нашем примере, люди имели уникальные данные, недоступные больше нигде. Если кто-то захочет эти данные, они смогут использовать тот же подход с ++$id, чтобы захватить в свои руки данные и заполнить ими собственное приложение, что довольно легко создаст нового конкурента, а если у нового конкурента будет ещё и немного лучшее приложение, то этот конкурент может потенциально разорить стартаперов.

Альтернативы

Существуют альтернативы этому, которые можно использовать практически в любом сценарии.

Обфускация ID

Если вы застряли с 1, 2, 3 в БД из-за придирчивой ORM или из нежелания изменить существующую схему и все данные, идущие с ней, то вы можете хранить свои идентификаторы как раньше, но «скрыв» их!

Обфускация позволяет превратить 1 в «df234FSafd» и «p363fdte7» в 2364. Ваши идентификаторы остаются такими же, но пользователь не может сделать ++$id где-либо, потому что «df234FSafd» + 1 ничего не даст.

Используется скрытый секретный ключ, без которого строки не обратимы, таким образом, они относительно безопасны.

PHP

Ruby

  • obfuscate_id — Rails только извиняется перед другими людьми, но выглядит хорошо

Python

  • Opaque ID — обфускация для целочисленных идентификаторов

JavaScript, Python, Ruby, PHP, Java, Scala, Perl, Swift, Clojure, Objective-C, C, C++11, Go, Erlang, Lua, Haskell, Elixir, Rust, ColdFusion, Groovy, Kotlin, Nim, VBA, ActionScript, CoffeeScript, Bash and for Node.js & .NET

  • HashIDs — очевидно, они не так безопасны и соль можно подделать приблизительно с 30 хэшами, так что, наверное, не используйте это, но, если вы застряли на чём-то ещё…

Универсальные уникальные идентификаторы

UUID (Universally Unique Ids) является классным способом создать действительно уникальные идентификаторы для ваших записей, не полагаясь на автоматический инкремент БД, чтобы сделать их уникальными.

UUID могут использоваться вместо обычных ID. Они выглядят примерно так:

de305d54-75b4-431b-adb2-eb6b9e54601

И снова, это не поддерживает ++$id.

Вдобавок ко всему, две записи, сделанные в ту же самую долю секунды, не будут иметь один и тот же UUID, поскольку «универсальность» приходит и сюда. Вы можете использовать UUID для оффлайновой поддержки, подразумевая, что вы создаёте элемент локально, выдаёте ему UUID, а затем синхронизируете с базой данных, когда ваш пользователь выходит из метро, и вы поддерживаете целостность ваших идентификаторов и данных в целом.

Производительность для UUID была проверена на Twitter, и есть распространённое заблуждение, что UUID медленны и ужасны. Во-первых, не храните UUID как string (varchar или char). Сохраните их как двоичный файл и, если вы используете что-то, что предпочитает, чтобы первичные ключи были упорядочены, то тогда вы можете использовать упорядоченные UUID.

PHP

  • ramsey/uuid — PHP 5.4+ библиотека для генерации RFC 4122 версии 1, 3, 4 и 5 UUID

Ruby

Python

  • uuid — Встроенный!

Но если ваше приложение может получить его, то и пользователь тоже

Может быть, но как ваши пользователи добираются до данных?

В случае постраничного вывода, как например, список «Недавние события», просто ограничьте историю данных до нескольких дней.

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

Также сделайте ограничения. Если требуется регистрация приложения пользователями, то вы можете ограничить их учётные записи на свободном уровне, чтобы остановить загрузку ими всего на свете.

Тогда, если они попытаются загрузить весь набор данных, то это, по крайней мере, займёт длительное время и снова, надо надеяться, у вас будет шанс заметить подозрительную активность.

Как? Ищите приложения, регулярно поражающие свои ограничения. Посмотрите на материалы, которые случайным образом ищутся с перемещением по карте неестественным образом (люди не перемещаются по чёткой сетке слева направо).

Автоматизируйте процессы обнаружения, и стреляйте по электронной почте ублюдков, пытающихся загрузить набор данных. У вас будет их электронная почта, потому что они зарегистрировались в системе, и, если они действительно глупы, то будут использовать свою рабочую почту. Я видел, что происходит, и у нас был миленький чат.


Примечание

Это авторский перевод статьи «Auto-Incrementing Ids: Giving your Data Away | Phil Sturgeon».

Комментарии

  1. SEO Dubai пишет:

    в PHP я использую uniqid() — получаем строку из 13 символов, что смотриться красивее md5 или uuid. Плюс не вероятности что идентификатор уже будет существовать в БД.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *