Строковый ключ

Статус
Закрыто для дальнейших ответов.

timpaul

New Member
Регистрация
08.01.2011
Сообщения
9
Есть желание сделать в базе строковый ключ (ID), генерируемый случайно, для того, чтобы пользователь не мог вызвать запись, набрав произвольный числовой ID, создаваемый автоинкрементом.

Оптимально ли это или есть более правильное решение? Может, сделать два столбца: ключ в виде INT с автоинкрементом, а в другой случайный CHAR и строить запрос по нему?

Заранее благодарен,
 

tigra60

Спасатель
Регистрация
10.12.2009
Сообщения
1 990
Если у вас пользователь может вызвать запись, набрав произвольный числовой ID, то никакие строковые ключи не помогут. Кроме того, числовой ввод гораздо легче защитить от SQL-инъекции (как правило, достаточно intval()).

Если вам уж так нужен уникальный идентификатор, используйте md5(timestamp()) и храните его в поле типа VARCHAR(32). А для особо параноидальных случаев - md5(timestamp().'abracadabra'), где 'abracadabra' - любой ключ по вашему выбору. (Держите его в строгом секрете :)).
 

timpaul

New Member
Регистрация
08.01.2011
Сообщения
9
Спасибо за комментарий.


Если у вас пользователь может вызвать запись, набрав произвольный числовой ID, то никакие строковые ключи не помогут. Кроме того, числовой ввод гораздо легче защитить от SQL-инъекции (как правило, достаточно intval()).
Пользователь введет в форме последовательность символов, по которой будет производится поиск по конкретному столбцу в базе. Если это случайное сочетание символов, то подобрать его сложно. Если это целое число с автоинкрементом, то вводи их подряд и получай записи. Разве не так?


Если вам уж так нужен уникальный идентификатор, используйте md5(timestamp()) и храните его в поле типа VARCHAR(32). А для особо параноидальных случаев - md5(timestamp().'abracadabra'), где 'abracadabra' - любой ключ по вашему выбору. (Держите его в строгом секрете :)).
Это мне сразу понять сложно :blush:, но почитаю. А в этом случае отдельный столбец ID делать в таблицу или не нужно? И можно ли это обрезать до, например, 10 символов без ущерба для уникальности идентификатора?
 

tigra60

Спасатель
Регистрация
10.12.2009
Сообщения
1 990
Пользователь введет в форме последовательность символов, по которой будет производится поиск по конкретному столбцу в базе. Если это случайное сочетание символов, то подобрать его сложно. Если это целое число с автоинкрементом, то вводи их подряд и получай записи. Разве не так?
Здесь очень трудно говорить абстрактно. Приведите, пожалуйста пример поконкретнее, тогда можно будет обсудить этот вопрос.
В целях безопасности, пользователя нужно как можно более ограничить в возможностях ввода. Это, кстати, и в его интересах. Чем меньше возможность выбора для ввода, тем легче пользователю выбрать именно то, что ему нужно. Простой пример - ввод даты. Сравните удобства ввода даты в трех случаях - текстовое поле, выбор дней, месяцев и лет из выпадающих списков и выплывающий календарь. Как будет удобнее для пользователя и безопаснее для системы? Чем меньше вариантов выбора, тем меньше головной боли у нормального пользователя, и, наоборот, больше у шаловливого пионера-недоумка.

По поводу уникального идентификатора - все предельно просто. Хэш функция md5 возвращает 32-значное шестнадцатеричное число, причем один и тот же аргумент дает один и тот же хэш, что позволяет с успехом использовать эту функцию для паролей. Обратное преобразование напрямую невозможно (кроме, конечно, тупого подбора).
А c timestamp() я немного ошибся. Простите! Функция называется time() и возвращает количество секунд, прошедших с начала Эпохи Unix (The Unix Epoch, 1 января 1970, 00:00:00 GMT). Достаточно уникальное число - каждую секунду - другое! Но даты следуют подряд, одна за другой. Вот md5 и устраняет этот "недостаток".
Однако, сократив хэш до 10 символов, можно нарваться на повторы.
 

timpaul

New Member
Регистрация
08.01.2011
Сообщения
9
Здесь очень трудно говорить абстрактно. Приведите, пожалуйста пример поконкретнее, тогда можно будет обсудить этот вопрос.
В целях безопасности, пользователя нужно как можно более ограничить в возможностях ввода. Это, кстати, и в его интересах. Чем меньше возможность выбора для ввода, тем легче пользователю выбрать именно то, что ему нужно. Простой пример - ввод даты. Сравните удобства ввода даты в трех случаях - текстовое поле, выбор дней, месяцев и лет из выпадающих списков и выплывающий календарь. Как будет удобнее для пользователя и безопаснее для системы? Чем меньше вариантов выбора, тем меньше головной боли у нормального пользователя, и, наоборот, больше у шаловливого пионера-недоумка.
Например, есть база упрощенно такого вида
| id | code | variable |
| 1 | a3b5 | var1 |
| 2 | lre8 | var2 |
| 3 | j378 | var3 |
пользователь должен иметь возможность задать код по которому ему сайт вернет предназначенную ему запись. Если вызывать по ID, то очень легко прочитать все записи, а это не нужно. Код набирать в простом текстовом поле формы. Если набран не правильно, то просто сообщение об отсутствии записи. Есть в этом какая-то опасность?

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

По поводу уникального идентификатора - все предельно просто. Хэш функция md5 возвращает 32-значное шестнадцатеричное число, причем один и тот же аргумент дает один и тот же хэш, что позволяет с успехом использовать эту функцию для паролей. Обратное преобразование напрямую невозможно (кроме, конечно, тупого подбора).
А c timestamp() я немного ошибся. Простите! Функция называется time() и возвращает количество секунд, прошедших с начала Эпохи Unix (The Unix Epoch, 1 января 1970, 00:00:00 GMT). Достаточно уникальное число - каждую секунду - другое! Но даты следуют подряд, одна за другой. Вот md5 и устраняет этот "недостаток".
Однако, сократив хэш до 10 символов, можно нарваться на повторы.
А если отрезать слева? ;) Или не получится?

Еще раз спасибо за участие.
 

tigra60

Спасатель
Регистрация
10.12.2009
Сообщения
1 990
Да, в приведенном примере уникальный идентификатор - разумное решение. Но от ID я бы тоже не отказывался.

А по поводу отрезать слева - также опасно, как и отрезать справа. Если взять хэши возрастающей последовательности чисел, наример, 10, 11, 12, 13 и 14, то они не будут отличаться только правой частью.
 

timpaul

New Member
Регистрация
08.01.2011
Сообщения
9
Да, в приведенном примере уникальный идентификатор - разумное решение. Но от ID я бы тоже не отказывался.

А по поводу отрезать слева - также опасно, как и отрезать справа. Если взять хэши возрастающей последовательности чисел, наример, 10, 11, 12, 13 и 14, то они не будут отличаться только правой частью.

То есть надо в PHP генерить строку, проверять уникальность в базе и потом записывать. А не может случайно в один момент несколько пользователей получить однаковый код? Генерирование и проверка до записи в базу займет какое-то время, пусть и минимальное, а значит теоретически возможно дублирование.

А все хэши 32-значные?
 

tigra60

Спасатель
Регистрация
10.12.2009
Сообщения
1 990
Функция uniqid - генерирует уникальный id.

Описание
string uniqid (string prefix [, bool lcg])

uniqid() возвращает уникальный идентификатор с префиксом на основе текущего времени в микросекундах. Это prefix может использоваться, например, если вы генерируете идентификаторы одновременно на нескольких хостах, что может сгенерировать идентификатор в ту же микросекунду. Prefix может быть длиной до 114 символов.

Если необязательный параметр lcg TRUE, uniqid() добавит дополнительную "combined LCG" энтропию в конце return-значения, что должно сделать результат более уникальным.

С пустым prefix возвращаемая строка будет иметь длину 13 символов. Если lcg равен TRUE, длина будет 23 символа.


Если вам нужен уникальный идентификатор или лексема и вы намереваетесь выдать эту лексему пользователю по сети (т.е. как куки сессии), рекомендуется использовать её вместе со строками.
Код:
$token = md5(uniqid("")); // без префикса
$better_token = md5(uniqid(rand(),1)); // лучше, труднее взломать
Это создаст 32-символьный идентификатор (128-битное 16-ричное число), который очень трудно угадать.
 
Статус
Закрыто для дальнейших ответов.
Верх Низ