Покинул форум
Сообщений всего: 561
Дата рег-ции: Нояб. 2009
Помог: 2 раз(а)
У меня генерируется случайная строка, которая потом хиширую через md5 и сохраняется в базу. По сути получается что та типа пароля. Хочу избежать такого случая что если строка которая сгенерировалась была ранее записана базу, тогда перезапустилась бы функция генерации, и так до тех пор пока строка не станет уникальной. Как это сделать?
Покинул форум
Сообщений всего: 561
Дата рег-ции: Нояб. 2009
Помог: 2 раз(а)
Viper пишет:
Вам что нужно? Рандомную строку никогда не повторяющуюся или пароль зашифровать?
да, чтоб рандомная строка не когда не повторялась
3d_killer
Отправлено: 20 Марта, 2016 - 14:29:07
Участник
Покинул форум
Сообщений всего: 1916
Дата рег-ции: Апр. 2011 Откуда: Ростов-на-Дону
Помог: 21 раз(а)
писать в базу только потом сравнивать если есть то генерировать заново
kuller
Отправлено: 20 Марта, 2016 - 14:45:26
Частый посетитель
Покинул форум
Сообщений всего: 561
Дата рег-ции: Нояб. 2009
Помог: 2 раз(а)
3d_killer пишет:
писать в базу только потом сравнивать если есть то генерировать заново
вот в этом и вопрос... как это написать? понятно что должен быть запущен цыкл... но как это написать? Ведь сверка строки получается должна идти внутри цыкла, а цыклу надо дать какое та условие сколько раз выполняться
3d_killer
Отправлено: 20 Марта, 2016 - 15:00:38
Участник
Покинул форум
Сообщений всего: 1916
Дата рег-ции: Апр. 2011 Откуда: Ростов-на-Дону
Помог: 21 раз(а)
на работоспособность не проверял, но что то типо того:
public static function Init(){self::$instance=new Password();}
public static function GetPassword(){returnself::$password;}
}
Password::Init($lenght);
echo(Password::GetPassword());
но скажу что задумка ваша не очень сама по себе
спасибо работает! Я понимаю что количество запросов к базе иза этого может в разы возрасти, но по другому не сделать. Да, и возможно что всегда false будет возвращать т.к. эти записи раз в сутки удаляться будут, но лучше думаю перестраховаться.
не могу понять Password::Init($lenght); что за переменная?
3d_killer
Отправлено: 20 Марта, 2016 - 15:48:46
Участник
Покинул форум
Сообщений всего: 1916
Дата рег-ции: Апр. 2011 Откуда: Ростов-на-Дону
Помог: 21 раз(а)
количество символов (Добавление)
строка Password::Init($lenght); это создание экземпляра класса с заданым количеством символов в пароле (Добавление)
только тут так private static function CheckBD($password)
Мелкий
Отправлено: 20 Марта, 2016 - 15:59:44
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Такс, во-первых, rand, mt_rand и прочие shuffle для генерировать паролей использовать нельзя. Используйте random_int, random_bytes (для php5 - есть слой совместимости). openssl_random_pseudo_bytes желательно тоже не использовать.
По реализации в базе безопасно для конкурентного доступа:
if($e->getCode()=='код ошибки на уникальный индекс'){
continue;// плюс, возможно, счётчик попыток
}else{
throw $e;
}
}
}
Как можно заметить, способ безопасный для конкуретного доступа, но нетранзакционный. Ошибка insert'а потребует rollback. Зато просто и не требует лишних действий.
Можно предварительно делать селект этого значения, но это race condition. Можно внезапно споткнуться.
Способ номер далее:
insert into tablename .... select password from (select :password as password) dt where not exists (select 1 from tablename where tablename.passwordfield = dt.password)
Можно ли тут споткнуться - надо усиленно выяснять для конкретной СУБД. И по mysql и по postgresql честно не помню.
Способ обратный. Конкурентно-безопасный, транзакционный, детерминирован по затрачиваемому времени на обработку запроса (т.е. нет цикла с условием выхода на непонятно какой попытке). Но требует дополнительного обслуживания.
Делаете отдельную табличку из буквально пары полей, в которую изначально генерируете, перемешиваете и пишете какое-то число случайных строк. Лямов этак 10.
Когда понадобилась случайная строка - делаете select for update + delete из этой таблицы (для postgresql >=9.5 стоит посмотреть на select for update skip locked). Для более случайного распределения, можете выбирать where id > случайное_число на первой попытке и только если промахнулись, то без where
Очевидна проблема, что когда-нибудь предварительно сгенерированные строки кончатся и надо предусмотреть механизм их дальнейшего наполнения.
----- PostgreSQL DBA
Мелкий
Отправлено: 21 Марта, 2016 - 13:08:50
Активный участник
Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009 Откуда: Россия, Санкт-Петербург
Помог: 618 раз(а)
Хм, забыл ещё вариацию первого варианта, которая как раз транзакционная:
mysql insert ignore
postgresql 9.5: insert ... ON CONFLICT DO NOTHING
Если affected_rows = 1, значит такой хэш успешно записали. Если 0 - то надо генерировать другой.
----- PostgreSQL DBA
kuller
Отправлено: 28 Марта, 2016 - 13:25:38
Частый посетитель
Покинул форум
Сообщений всего: 561
Дата рег-ции: Нояб. 2009
Помог: 2 раз(а)
вот опять данная штука потребовалась для другого проекта. Там должен генерироваться случайны уникальный id. Здесь я решил заранее сгенерировать таблицу с уникальными id и написал следующее
$t=$db->super_query("SELECT * FROM ls_generate WHERE user='$m'");
if($r==$t['user'])
{
echofalse;
}else{
echotrue;
}
}
public static function Init(){self::$instance=new Password();}
public static function GetPassword(){returnself::$password;}
}
$c=99999;
for($i=11111;$i<$c;$i++)
{
Password::Init($lenght);
$code= Password::GetPassword();
if($code== 11111 OR $code== 22222 OR $code== 33333 OR $code== 44444 OR $code== 55555 OR $code== 66666 OR $code== 77777 OR $code== 88888 OR $code== 99999 OR $code== 00000)
{
$db->query("INSERT INTO ".PREFIX."_generate (user, gold) VALUES('$code', '1')");
}else{
$db->query("INSERT INTO ".PREFIX."_generate (user, gold) VALUES('$code', '0')");
}
}
?>
т.е. там где 5 одинаковых цифр надо gold присваивать 1. Сделались записи и я решил посмотреть как записались id под gold=1 и увидел что есть повторяющие айдишники. Простые айди я не проверял... может и там есть повторения.... В чем моя ошибка?
Все гости форума могут просматривать этот раздел. Только зарегистрированные пользователи могут создавать новые темы в этом разделе. Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.