Создание частных, уникальных, безопасных URL-адресов

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

#    Google Calendar
3qq6jlu04ptlhmb9fencsu5t2k
#    Private
3qq6jlu04ptlhmb9fencsu5t2k
#    Private 'token'
163a0afe7fkb1ba2acd04c11ef0eefe8
#    LogMeIn
#    1024 bit - 128 Character URL
72oxuj0fzefqo3fu04xjtvmd0adj2948rfh7g5by4forkwcy7t651z7hcb6kjjgqkxmvmfqpyrcfy15z1fto8ewcxstjc6avicag7d5qnoimsm19kb9kgi9i7v6z01d5

Я склоняюсь к 128-символьному и 1024-битному стилю, так как он кажется очень безопасным. Думаю, я мог бы создать четыре хэша MD5 и объединить их, но действительно ли это эффективно?

У меня есть два конкретных намерения для такого URL-адреса, но я уверен, что есть и другие, кому это может пригодиться.

1) Мгновенный ярлык / значок входа для пользователей

2) Одноразовый URL (ссылки для восстановления пароля)

Ответов (7)

Решение

Обновлять:

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

Для мгновенного входа в систему не существует действительно безопасного способа иметь один URL.

Да, вы можете сгенерировать URL-адрес, который будет чертовски невозможно угадать, но это не дает вам супербезопасности. Если вы хотите запомнить пользователей, почему бы не использовать зашифрованный файл cookie для аутентификации?

В приведенном вами примере Календарь Google не входит в систему только через URL-адрес, вы должны сначала пройти аутентификацию, прежде чем URL-адрес будет что-то значить.

Например, нажатие на календарь Google из моего Gmail дает мне:

https://www.google.com/calendar/render?tab=mc&gsessionid=-LTeHrnKoeAbDcVaN68NHA

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

Старый пост:

Вы можете сгенерировать GUID в PHP с помощью com_create _guid и использовать его.

В Linux, я думаю, вы можете использовать uuid_create или этот код отсюда :

<?php
 function guid(){
 if (function_exists('com_create_guid')){
       return com_create_guid();
   }else{
       mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
       $charid = strtoupper(md5(uniqid(rand(), true)));
       $hyphen = chr(45);// "-"
       $uuid = chr(123)// "{"
               .substr($charid, 0, 8).$hyphen
               .substr($charid, 8, 4).$hyphen
               .substr($charid,12, 4).$hyphen
               .substr($charid,16, 4).$hyphen
               .substr($charid,20,12)
               .chr(125);// "}"
       return $uuid;
   }
}
echo guid();
?>

Идентификатор должен быть невозможно угадать, идентификаторы GUID уникальны, но их несложно угадать.

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

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

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

  2. Или возьмите наибольшее число, которое примут ваши пользователи

Теперь у вас есть «безопасный» номер, вы можете просто преобразовать его в десятичное, шестнадцатеричное или base64 и использовать эту строку.

Просто создайте GUID. Однако важно, что это не последовательный GUID старого стиля.

Однако похоже, что php не имеет собственной функции генерации GUID. Функция com_create_guid, предложенная в другом ответе, кажется, доступна только в php при работе в Windows.

На странице руководства для него есть предложенная пользователем альтернатива com_create_guid для не-Windows:

function guid(){
    if (function_exists('com_create_guid')){
        return com_create_guid();
    }else{
        mt_srand((double)microtime()*10000);//optional for php 4.2.0 and up.
        $charid = strtoupper(md5(uniqid(rand(), true)));
        $hyphen = chr(45);// "-"
        $uuid = chr(123)// "{"
                .substr($charid, 0, 8).$hyphen
                .substr($charid, 8, 4).$hyphen
                .substr($charid,12, 4).$hyphen
                .substr($charid,16, 4).$hyphen
                .substr($charid,20,12)
                .chr(125);// "}"
        return $uuid;
    }
}

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

Попробуйте uniqid - и, возможно, объедините его с хешем md5, как показано в примерах:

// no prefix
// works only in PHP 5 and later versions
$token = md5(uniqid());

// better, difficult to guess
$better_token = md5(uniqid(rand(), true));

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

Для обрезки дополнительных фигурных скобок

$ guid = strtolower (обрезать (com_create_guid (), "{}")); (PHP 5 или новее)

Я бы избегал этого для:

1) Мгновенный ярлык / значок входа для пользователей

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

Если вы хотите убедиться, что URL-адрес уникален и может использоваться только ограниченное количество раз:

  • Держите небольшую базу данных с полями , как: RandomKey, InternalURL, Counter,TimeStamp

  • Создайте случайное число из достаточно большого пула.
    Непоследовательных GUID должно быть достаточно

  • Сохраните его в своей базе данных как RandomKeyвместе с фактическим внутренним URL-адресом или кодом ресурса, необходимым вашей системе для обработки этого URL-адреса, и отметкой времени.

  • Когда пользователь щелкает или вводит URL-адрес, проверьте его по этой базе данных: если TimeStampон слишком старый или Counterслишком высокий, примите соответствующие меры (например, если вы хотите, чтобы этот URL-адрес был доступен в течение ограниченного времени или определенное количество раз. ).
    В противном случае просто обработайте запрос с помощью InternalURLи отправьте результат обратно пользователю.

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

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

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