HashIDs. Что Это и Зачем Их Использовать?
В REST API для CRUD операций часто используются первичные ключи для доступа к ресурсу. Они часто реализуются как суррогатные ключи с использованием последовательных целочисленных значений. Это самый простой и эффективный способ указать данные/запись для извлечения.
Проблема в том, что это угроза безопасности API, т.к. мы показываем пользователю необработанные идентификаторы, особенно последовательные. Так мы даём пользователям возможность оценить количество записей и легко угадать значения других записей. Можно использовать GUID, но с ним есть свои проблемы.
Кроме того, у вас может быть унаследованная БД с уже определёнными идентификаторами. Например, в моей практике был случай, когда часть данных из результатов поиска, который был изначально доступен только зарегистрированным пользователям, было решено предоставлять публично. Получилось, что изначально закрытые целочисленные id теперь становились публично доступными.
Одним из решений является использование хэш-значений. Это эффективный подход для генерации неугадываемых непоследовательных идентификаторов, полученных из последовательных идентификаторов (например, целых чисел).
[HttpGet]Приведенный выше метод API принимает идентификатор аргумента строкового типа. Библиотека HashIds (недавно переименованная в Sqids) предоставляет готовую к использованию реализацию с функцией Decode, которая преобразует строковый идентификатор (предварительно полученный с помощью функции Encode) обратно в исходный числовой идентификатор.
public IActionResult Get([FromRoute] string id)
{
int[] intId = _hashids.Decode(id);
if (intId.Length == 0) return NotFound();
var user = _userService.GetUser(intId[0]);
if (user is null) return NotFound();
return Ok(user);
}
Теперь мы можем получить запись из нашего хранилища данных, где данные по-прежнему хранятся с использованием исходного последовательного идентификатора.
Как это работает?
HashIDs использует принцип преобразования десятичных чисел в шестнадцатеричные, однако base62 в качестве алфавита. Кроме того, алфавит перемешивается на основе уникального значения соли, которое может быть установлено пользователем. Это делает каждый алгоритм реализации уникальным и снижает риски безопасности. Идентификаторы нигде не сохраняются, а должны вычисляться каждый раз. Это позволяет нам менять соль без изменения данных. Таким образом для каждого запроса потребуется как минимум два преобразования: декодирование полученной из запроса строки в id и обратное кодирование id в строку при возврате результата клиенту. Скорость кодирования/декодирования измеряется в наносекундах, поэтому за производительность в подавляющем большинстве случаев переживать не придётся.
Итого
Хэши — это эффективный подход для приложений малого и среднего масштаба, которые не требуют более сложных стратегий, вроде идентификаторов Snowflake (объединение различных метаданных, таких как метки времени, идентификаторы сегментов и т. д.). И многие отраслевые решения, такие как GraphQL, используют простые хэши получая преимущества, изложенные выше.
Источник: https://stefandjokic.tech/blog