Как сгенерировать неосуществимый «крошечный URL» на основе идентификатора?

Я заинтересован в создании крошечных ссылок, похожих на URL. Моя идея состояла в том, чтобы просто сохранить инкрементный идентификатор для каждого размещенного длинного URL, а затем преобразовать этот идентификатор в его базовый вариант 36, как показано в PHP:

$tinyurl = base_convert($id, 10, 36)

Проблема здесь в том, что результат является предположительным, в то время как трудно угадать, каким будет следующий URL, при этом он будет коротким (крошечным). Например. атм, если мой последний tinyurl был a1, следующий будет a2. Это плохо для меня.

Итак, как я могу убедиться, что получающийся в результате крошечный URL-адрес не такой предсказуемый, но все же короткий?

6
задан Charles 24 December 2012 в 21:22
поделиться

8 ответов

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

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

По сути, вы хотите объявить n из N допустимых идентификаторов. Выберите N меньше, чтобы сделать URL-адреса короче, и уменьшите n, чтобы сгенерировать URL-адреса, которые трудно угадать. Увеличьте n и N, чтобы генерировать больше URL-адресов, когда будут взяты более короткие.

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

9
ответ дан 8 December 2019 в 05:52
поделиться

Я бы просто crc32 url

$url = 'http://www.google.com';
$tinyurl = hash('crc32', $url ); // db85f073

cons: константа 8 символов длинный идентификатор

5
ответ дан 8 December 2019 в 05:52
поделиться

Это действительно дешево, но если пользователь не знает, что это происходит, то это не так угадывается, но префикс и постфикс фактического идентификатора с 2 или 3 случайными цифрами / буквами.

Если бы я увидел 9d2a1me3, я бы не догадался, что dm2a2dq2 был следующим в серии.

4
ответ дан 8 December 2019 в 05:52
поделиться

Попробуйте Xor'ing $id с некоторым значением, например, $id ^ 46418 - и для преобразования обратно в исходный идентификатор вы просто снова выполните тот же Xor, т.е. $mungedId ^ 46418. Сложите это вместе с вашим base_convert и, возможно, некоторой замену символов в результирующей строке, и будет довольно сложно угадать URL-адрес.

2
ответ дан 8 December 2019 в 05:52
поделиться

Другой способ - установить максимальное количество символов для URL-адреса (скажем, n ). Затем вы можете выбрать случайное число от 1 до n !, которое будет вашим числом перестановки.

Для какого нового URL вы должны увеличить идентификатор и использовать номер перестановки, чтобы связать фактический идентификатор, который будет использоваться. Наконец, вы должны кодировать свой URL-адрес по базе 32 (или что-то еще). Это было бы совершенно случайно и полностью обратимо.

2
ответ дан 8 December 2019 в 05:52
поделиться

Если вам нужна инъективная функция, вы можете использовать любую форму шифрования. Например:

<?php
$key = "my secret";
$enc = mcrypt_ecb (MCRYPT_3DES, $key, "42", MCRYPT_ENCRYPT);
$f = unpack("H*", $enc);
$value = reset($f);
var_dump($value); //string(16) "1399e6a37a6e9870"

Чтобы перевернуть:

$rf = pack("H*", $value);
$dec = rtrim(mcrypt_ecb (MCRYPT_3DES, $key, $rf, MCRYPT_DECRYPT), "\x00");
var_dump($dec); //string(2) "42"

Это не даст вам число по основанию 32; он предоставит вам зашифрованные данные с каждым байтом, преобразованным в базу 16 (т. е. преобразование является глобальным). Если вам действительно нужно, вы можете тривиально преобразовать это в базу 10, а затем в базу 32 с помощью любой библиотеки, которая поддерживает большие целые числа.

1
ответ дан 8 December 2019 в 05:52
поделиться

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

0
ответ дан 8 December 2019 в 05:52
поделиться

В итоге я создал md5-сумму идентификатора, использовал первые 4 буквенно-цифровых символа и, если это дубликат, просто увеличивал длину, пока он не перестал быть дубликатом.

function idToTinyurl($id) {
    $md5 = md5($id);
    for ($i = 4; $i < strlen($md5); $i++) {
        $possibleTinyurl = substr($md5, 0, $i);
        $res = mysql_query("SELECT id FROM tabke WHERE tinyurl='".$possibleTinyurl."' LIMIT 1");
        if (mysql_num_rows($res) == 0) return $possibleTinyurl;
    }
    return $md5;
}

Принял ответ relet, так как он привел меня к этой стратегии.

-1
ответ дан 8 December 2019 в 05:52
поделиться
Другие вопросы по тегам:

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