Скрыть идентификаторы автоинкремента в параметре GET (PHP)

StackOverflow https://stackoverflow.com/questions/1426570

Вопрос

Редактировать: С тех пор я нашел и опубликовал эффективное и элегантное решение, которое преобразует идентификаторы типа 3141592 к таким строкам, как vJST и задом наперед.Это доступно для PHP здесь:

https://github.com/delight-im/PHP-IDs

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

Проблема:

У меня есть динамические страницы на PHP, где содержимое отображается в соответствии с заданным идентификатором.Идентификатор всегда передается через параметр GET:page.php?id=X Это вызывает проблему:Посетители сайта могут перечислять идентификаторы и просто просматривать все различные страницы контента.Конечно, это не должно быть возможно.

Как это можно было бы решить?

Мой подход заключается в кодировании всех идентификаторов в ссылках и формах, которые позже используются в качестве параметра GET.В начале каждой страницы данный идентификатор декодируется в "реальный" идентификатор, который используется в базе данных.Хороший ли это подход?Выбрали бы вы другой путь?

Возможное решение моего подхода:

Я бы преобразовал целочисленный идентификатор в базовое 38-е целое число и заменил цифры символами заданного списка.Я бы использовал эти символы для кодированного идентификатора строки:

a-z 0-9 - _

Использовали бы вы и другие символы?Для этих персонажей мой сценарий был бы таким:

function id2secure($old_number) {
    $alphabet_en = array(0=>'1', 1=>'3', 2=>'5', 3=>'7', 4=>'9', 5=>'0', 6=>'2', 7=>'4', 8=>'6', 9=>'8', 10=>'a', 11=>'c', 12=>'e', 13=>'g', 14=>'i', 15=>'k', 16=>'m', 17=>'o', 18=>'q', 19=>'s', 20=>'u', 21=>'w', 22=>'y', 23=>'b', 24=>'d', 25=>'f', 26=>'h', 27=>'j', 28=>'l', 29=>'n', 30=>'p', 31=>'r', 32=>'t', 33=>'v', 34=>'x', 35=>'z', 36=>'-', 37=>'_');
    $new_number = '';
    while ($old_number > 0) {
        $rest = $old_number%38;
        if (!isset($alphabet_en[$rest])) { return FALSE; }
        $new_number .= $alphabet_en[$rest];
        $old_number = floor($old_number/38);
    }
    $new_number = strrev($new_number);
    return $new_number;
}

Дополнительный вопрос:

Какой была бы обратная функция для моей функции?

Я надеюсь, что вы сможете мне помочь.Спасибо!

Это было полезно?

Решение

Могут ли пользователи попасть на страницы через веб-сайт?Если ответ "да", то вам следует спросить себя, действительно ли это проблема или нет.

Если нет, то проблема в том, что вы не защищаете свои страницы, или, другими словами:вы полагаетесь на неизвестность для обеспечения безопасности, что никогда не является хорошим ходом.

Мой совет?Либо обезопасьте свои страницы, чтобы к ним могли получить доступ только нужные пользователи, либо не беспокойтесь об этом.

Если вам действительно нужно беспокоиться об этом, просто введите дополнительное поле, которое должно быть правильным для данной страницы.Я бы не стал создавать это на основе идентификатора.Возможно, сгенерируйте другой номер или идентификатор GUID при создании записи страницы в базе данных.Если оба поля неверны, то не отображайте страницу.

Забудьте о простой замене символов и других наивных методах запутывания.Это пустая трата вашего времени.

Редактировать: если вам нужны непоследовательные идентификаторы одинаковой длины, рассмотрите возможность использования UUID вместо первичных ключей с автоматическим увеличением.В основном это делается на уровне приложения:

  • Измените свой первичный ключ на char(36);
  • В вашем операторе insert вы должны установить ключ и заполнить его с помощью функции MySQL UUID().

Взгляните на К UUID или не к UUID ? и UUID как первичный ключ.Это приводит к снижению производительности (в частности, потому, что вы используете символы, а не целые числа для поиска), но если у вас нет большого объема (более 1 миллиона строк) или данных, это, вероятно, не будет проблемой на практике.

Другие советы

Используйте алгоритм контрольной суммы, подобный Luhn:

$id = 1337;

$_GET['id'] = Luhn($id, 3); // 1337518, adds 3 checkdigits
$_GET['id'] = Luhn_Verify($_GET['id'], 3); // 1337, returns the original number of false if validation fails

echo $_GET['id']; // 1337

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

$id = Luhn_Verify($_GET['id'], 3);

if ($id === false)
{
    // someone is trying to guess the ID
}

else
{
    // $id is valid, do the DB stuff here
}

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

Вы могли бы использовать случайные числа для идентификаторов.Это предотвратило бы легкое угадывание идентификаторов страниц и порядка страниц (опять же, если это имеет значение).

Вы также можете использовать Хашиды для кодирования / декодирования ваших идентификаторов.

Этот код был написан с намерением разместить созданные идентификаторы в видимых местах - например, в URL.

Hashids - это небольшая библиотека с открытым исходным кодом, которая генерирует короткие, уникальные, непоследовательные идентификаторы из чисел.
Он преобразует числа типа 347 в строки типа “yr8” или массив чисел типа [27, 986] в “3kTMd”.
Вы также можете расшифровать эти идентификаторы обратно.Это полезно при объединении нескольких параметров в один или просто использовании их в качестве коротких идентификаторов.

Я бы не стал заморачиваться по поводу этой "проблемы", но в любом случае я использовал в одном из своих проектов такой метод:

После сохранения новой страницы в БД я сгенерировал md5 of (record_id + page_title) и поместите его в специальное поле pagecode.Затем я получил доступ к страницам по этому коду страницы вместо идентификатора.И лучше проиндексировать pagecode поле в базе данных.

Посетители сайта могут перечислять идентификаторы и просто просматривать все страницы с различным контентом.Это конечно, не должно быть возможным.

Я не уверен, почему это должно быть проблемой - люди могут просматривать список всех (общедоступных, проиндексированных ботом Googlebot) страниц на веб-сайте, просто набрав site:domain.com зайдите в Google и просмотрите их, если они пожелают.Изменение уникального индекса, который вы используете, этого не изменит.

Но если вы действительно не хотите, чтобы посетители получали прямой доступ к вашим страницам, простое быстрое решение - использовать POST вместо GET .

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top