Как создать уникальный идентификатор заказа (только для отображения пользователя) с фактическим идентификатором заказа?

ИЗМЕНИТЬ СНОВА: Я не хочу создавать другой вопрос, поэтому прошу здесь. У меня такая же ситуация. Но на этот раз мне нужен алгоритм на языке C. Кто-нибудь может мне помочь.

У меня есть следующая таблица.

CREATE TABLE IF NOT EXISTS `j741_order` ( `order_id` int(11) NOT NULL AUTO_INCREMENT, `buyer_id` int(11) NOT NULL, `subtotal` decimal(15,5) DEFAULT '0.00000', `discount` decimal(15,5) NOT NULL DEFAULT '0.00000', `shipping` decimal(15,5) DEFAULT '0.00000', `tax` decimal(15,5) DEFAULT '0.00000', `total` decimal(15,5) NOT NULL DEFAULT '0.00000', `currency` char(3) DEFAULT NULL, `status` int(11) NOT NULL DEFAULT '0', `created_date` datetime NOT NULL, `modified_date` datetime NOT NULL, PRIMARY KEY (`order_id`), KEY `idx_buyer_id` (`buyer_id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ; 

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

Как я могу получить уникальный идентификатор случайного заказа из оригинального заказа If

и вернуть исходный идентификатор заказа из этого случайного идентификатора заказа?

EDIT: Я не хочу создавать какие-либо другие поля.

Related of "Как создать уникальный идентификатор заказа (только для отображения пользователя) с фактическим идентификатором заказа?"

Если ваши требования:

  • Он должен быть обратимым (т. Е. С учетом только «случайного» идентификатора, вы можете найти исходный order_id)
  • Нет дополнительных столбцов
  • Вы не хотите показывать исходный / внутренний order_id пользователю вообще

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

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

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

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

Это строки скремблирования, которые я использовал (я использовал этот онлайн-скремблер вместо того, чтобы пытаться самостоятельно скрестить строку):

  $this->scramble1 = '0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ '; $this->scramble2 = 'UKAH652LMOQ FBDIEG03JT17N4C89XPV-WRSYZ'; 

Таким образом, код для создания нашего дружественного человека идентификатора заказа:

 <?php include 'encryption_class.php'; $crypt = new encryption_class(); $key = "A-COMPLETELY-RANDOM-KEY-THAT-I-HAVE-USED"; // Min length of 8 for encrypted string $min_length = 8; $order_id = 123456789; print "Original: " . $order_id . PHP_EOL; $encrypt_result = $crypt->encrypt($key, $order_id, $min_length); print "Encrypted: " . $encrypt_result . PHP_EOL; // DECRYPT $decrypt_result = $crypt->decrypt($key, $encrypt_result); print "Decrypted: " . $decrypt_result . PHP_EOL; ?> 

(Вам необходимо загрузить и сохранить файл * encryption_class * локально и включить его).

Я запустил этот код из командной строки и получил следующий вывод:

 Original: 123456789 Encrypted: 2UD5UIK9S Decrypted: 123456789 

Теперь у нас есть короткий, удобный для пользователя order_id, который можно использовать в URL-адресе, таком как http://myapp.example.com/order/view/2UD5UIK9S , и вам никогда не нужно отображать или передавать внутренний order_id своим пользователям ,

Заметки:

Зашифрованный код будет уникальным после того, как ваш order_id будет уникальным (поскольку это будет PK, он будет)

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

Убедитесь, что ваш секретный ключ случайный, сложный и содержит только символы в ваших переменных $ scramble.

Он запутывает только order_id.

Редактировать:

Хотя заполнение входной строки (order_id) создает определенное количество ramdomness, вы можете комбинировать это с ответом @ biakaveron для создания URL-адреса, например http://myapp.example.com/order/view/5cc46aea44e898c3b4e1303eb18d8161302cd367/2UD5UIK9S

  1. Создайте свой секретный ключ (любую строку) и сохраните в своих конфигурационных файлах (или в конфигурации БД).
  2. Создайте уникальный идентификатор: $newId = hash_hmac('sha1', $orderId, $secret_key).'-'.$orderId; , Таким образом, ваши страницы заказов будут выглядеть как http://example.com/order/show/123456...absdef-123 .
  3. Вы можете быстро получить оригинальный идентификатор заказа и проверить его:
  list($hash, $original) = explode($newId, '-', 2); if (hash_hmac('sha1', $original, $secret_key).'-'.$original === $hash) { // its a correct ID } else { // wrong hash, ignore it! } 

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

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

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

  • Поле varchar(something) или char(something) , которое получило бы лучший дисплей и было бы сложнее догадаться,
  • Он будет отображаться пользователю,
  • На нем будет UNIQUE индекс,
  • Но это не имело бы технического смысла для вашего кода.

GUID может быть идеей – но у меня есть возможность, что это может быть слишком долго …

Как насчет чего-то, основанного на первой букве имени пользователя, даты и некоторого случайного числа?
Было бы трудно догадаться, и все еще имеет немного смысл для пользователя …

Конечно, вы не сможете вычислить order_id из этого строкового идентификатора, но если он уникален, попробуйте простой запрос, и вы вернете order_id:

 select order_id from your_table where nice_looking_id = '...'; 

Вы можете любопытствовать, но я бы полностью рекомендовал добавить еще один столбец. Вот как я буду делать это с PHP.

 // do your insert // Retrieve last insert id $orderId = mysql_insert_id(); // get the current timestamp $time = time(); // Intersperse the $orderId into the $time to get a new "hash" $orderId = explode("", (string)$orderId); $time = explode("", (string)$time); $orderIdLength = sizeof($orderId); $newOrderId = ""; for ($i = 0; $i < $orderIdLength; ++$i) { $newOrderId .= $orderId[$i] . $time[$i]; } $newOrderId = (int)$newOrderId; 

Итак, если ваш фактический идентификатор заказа равен 489, а текущая временная метка – 1300778794, вы получаете идентификатор заказа, который выглядит как 418390. Если ваш клиент использует этот идентификатор заказа для чего-либо, вам просто нужно его сломать:

 $newOrderId = explode("", (string)$newOrderId); $length = sizeof($newOrderId); $oldOrderId = ""; for ($i = 0; $i < $length; $i = $i + 2) { $oldOrderId .= $newOrderId[$i]; } $oldOrderId = (int)$oldOrderId; 

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

Редактирование: так же, как быстро, вы можете использовать какой-либо другой способ генерации некоторого полуслучайного числа для заполнения id, отличного от time() . Например, вы можете сделать rand(pow(10, log10($orderId)), pow(10, log10($orderId)+1)) , который всегда возвращал бы какое-то случайное число с той же длиной, что и orderId.

Другой, очень простой метод – это base64 кодировать OrderID. Вы передаете кодированный идентификатор base64 клиенту вместо фактического идентификатора, а затем декодируете идентификатор, когда он возвращается. Я бы рекомендовал удалить знаки равенства с конца закодированной строки.

Преимущества:

  • Очень быстрая и простая обфускация фактического идентификатора

Недостатки:

  • Вы должны помнить, чтобы декодировать его
  • Умный пользователь легко понял бы это

$ original_id = [независимо];

 $salt = [very big private number/string/value]; $checksum = hexdec(substr(md5($original_id . $salt)), 0, 4); // Generate 16 bit checksum while(strlen($checksum) < 5) // make sure it's five digits long $checksum = "0" . $checksum; $user_facing_id = $checksum . $original_id; // Prepend original with checksum 

Вы можете вернуть исходный идентификатор с помощью substr ($ user_facing_id, 5), и вы даже можете проверить, является ли он действительным идентификатором заказа без опроса вашей базы данных, проверив равенство между dechex (substr ($ user_facing_id, 0, 5)) и substr ( md5 (substr ($ user_facing_id, 5). $ salt).

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

854bf1176798d77ecaf6b66cbe71a8fc1b0c1847

или

36698

Есть большая разница, когда дело доходит до wetware.

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

Что вы на самом деле пытаетесь избежать здесь? Я бы подумал, что вы просто хотите запретить пользователям видеть заказы других людей – в этом случае вам просто нужно использовать комбинацию идентификатора заказа и идентификатора пользователя для выбора заказов.

Конечно, общий объем заказов может считаться конфиденциальной информацией – в этом случае просто используйте порядковый номер, привязанный к идентификатору пользователя. Хотя вы явно не указали, какую СУБД вы используете, я предполагаю, что это mysql или производная на основе ядра, но следующее относится и к большинству реляционных СУБД:

Если вы добавите столбец в таблицу, описывающую пользователей со значением по умолчанию 0, то вы можете добавить триггеры в таблице заказов, чтобы автоматически извлекать, увеличивать и обновлять это значение для каждой вставки в таблице заказов, то есть никаких изменений, необходимых для кода в другом месте, за исключением поддержки «внешнего» заказа. Конечно, вам нужно будет выровнять это значение с соответствующим количеством уже размещенных заказов – что-то вроде ….

 ALTER TABLE buyers ADD COLUMN buy_ref_last INTEGER DEFAULT 0; ALTER TABLE orders ADD COLUMN buyer_order_ref INTEGER; UPDATE orders o SET buyer_order_ref = (SELECT COUNT(*) FROM orders r WHERE r.buyer_id=o.buyer_id AND r.order_id<o.order_id); 

(заметьте, я подозреваю, что вышеуказанное не будет запускаться непосредственно в MySQL, ему не нравятся подвыборки в той же таблице, что и обновление / удаление, – вам нужно развернуть логику в процедуру)

а также….

 UPDATE buyers b SET buy_ref_last=(SELECT MAX(buyer_order_ref) FROM orders o WHERE o.buyer_id=b.id);