|
|
|
| Что передавать в ссылке на активацию в письме????
id юзера, хэш его логина , маил..,.какой нибудь кей уже сгенерированный и записанный в бд...кто это реализовывал ,подскажите... | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 00:41)
| | Теоретически большой разницы нет, что передать, лишь бы это было ключем к активации. Но для "чистоты эксперемента" этот ключ должен быть уникальным. Одно из решений - "солёный" хэш E-mail'а. Допустим так:
<?
$code = md5($email.rand());
| Его нужно хранить в базе до момента активации или истечения времени, отведенного на активацию. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 05:36)
| | что помешает посчитать его третьей стороне, не владеющей ящиком? | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 11:17)
| | А какой смысл его считать? Помочь активировать аккуант? Информации полезной там нет, пусть считают на здоровье. Это же для антиспама процедура, не более того... | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 11:39)
| | так что передавать...
id и key
майл и кей
хэш логина и id
или что-то еще ..какой оптимальный вариант,учитываю что по какому либо переданному параметру будет выборка в бд ..как правильно... | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 16:41)
| | Вот потому, что выборка будет именно по этому ключу и нужно, что бы он был уникальным. Если Вы проверяете до этого наличие Е-mail в бд при валидации формы, то он и будет уникальным. А для того, что бы по "счастливой" случайности он не попал в лапы какого нибудь спам-бота, его нужно закэшировать, а для пущей важности еще "посолить". Только если есть автологин, то при активации записи, когда человек придет по ссылке, желательно попросить пароль, дабы не поставить кукис злоумышленнику. Можете поставить вместо него id, даже лучше наверное. Смотря какая структура таблиц при регистрации. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 11:39)
| | Это процедура, защищающая владельца сервера от возможного обвинения в спаме на чужой почтовый ящик.
И соответственно - владельца почтового ящика от спама со стороны сервера.
Если в качестве параметров удостоверяющей ссылки вы выбираете данные, только и лишь априори известные не только владельцу ящика - весь смысл процедуры теряется. | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 17:51)
| | Что-то я совсем запутался .... | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 18:50)
| | зачем вообще нужна активация по e-mail ? | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 17:51)
| | При регистрации с подтверждением на почтовый ящик информация о этом самом почтовом ящике как раз априори и не является особо секретной, так как в любом случае (используется) хранится в открытом виде. Так что по моему скрывать эту информацию каким то изощренным способом особой причины нет. Другое дело постараться обезопаситься от таких обвинений, сделав расшифровку этого кода, в случае перехвата, нерентабельной.
А вот как сделать идентификацию клиента по информации, известной только ему, я что то не понимаю... С чем то сверять её надо всё равно. Единственное, что приходит на ум - сначала провести проверку, а потом регистрацию. Но вопрос то именно в активации уже готовой учетной записи.
Помнится Вы преподали мне урок по системе восстановления пароля, может быть я и тут многого недопонимаю... | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 19:35)
| | >При регистрации с подтверждением на почтовый ящик информация о этом самом почтовом ящике как раз априори и не является особо секретной...
Вот именно.
Поэтому полагаться на то, что подтвердить регистрацию ссылкой, построенной на основе лишь этой информации, сможет только владелец почтового ящика и никто другой - нельзя.
Мы и ссылку то в ящик отправляем не от хорошей жизни, а лишь надеясь, что никто, кроме владельца ящика, по ней не перейдет. Что и будет косвенным подтверждением, что адрес, указанный при регистрации логина действительно принадлежит лицу, регистрирующему логин.
Представьте, допустим, спаммера, который имеет кучу е-мэйл адресов, и создает кучу логинов на форуме с целью завалить его рекламой.
Он просто сам нахеширует этих емэйлов и сам запросит все ссылки подтверждения. Вуаля. | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 19:40)
| | Но работа с почтой зачастую необходима (рассылки, уведомления и пр). Так хоть как то усложняется жизнь спамерам. Как он сможет нахэшировать соленые рандомом коды подтверждения, я чего то не пойму... К тому же обычно код подтверждения анулируется при третьей - пятой неудачной попытке. В любом случае ему придется принимать почту. Универсального решения все равно нет, если не считать премодерацию. Но ведь в данном случае и она как мертвому припарка. На соискателе ведь не написано - Я ЗЛОБНЫЙ СПАМЕР... | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 20:01)
| | Стоп. Прошу прощения. Случайной составляющей я и вправду не заметил. Прочел как $code = md5($email);.
Тогда пойдет. Ну то есть можно конечно придраться к источнику этой самой составляющей, но в принципе пойдет. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 20:01)
| | > Как он сможет нахэшировать соленые рандомом коды подтверждения, я чего то не пойму
Вашу "соль" можно угадать: это от нуля до RAND_MAX (часто 32768). Это сравнительно малое количество вариантов. | |
|
|
|
|
|
|
|
для: BinLaden
(20.01.2009 в 20:09)
| | Ну ведь больше трёх... В принципе наверное и впрямь лучше использовать id записи, хотя бы из этических соображений. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 20:16)
| | id записи?.. Думаете, так сложно его угадать? | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 20:16)
| | Уж он-то куда более детерминирован. Тем более - в потоке последовательных регистраций.
Что имеет смысл брать в качестве случайной составляющей в хеше здесь уже не раз обсуждалось... | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 20:29)
| | >Что имеет смысл брать в качестве случайной составляющей в хеше здесь уже не раз обсуждалось...
Вопрос не в случайности а именно в уникальности. А подобрать теоретически можно всё что угодно. Даже макака при определенном стечении обстоятельств может исполнить 7-ю сонату Бетховена. Дело не в невозможности а в нерентабельности. Прочность замков определяется тестовым временем на его взлом. Если оно превышает среднестатистическое время попытки домушника проникнуть в помещение, замок признается надежным. Сколько времени потребуется скрипту на такой подбор, если после трех неудачных попытках заставить его снова запрашивать код подтверждения с вводом адреса?? | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 20:44)
| | Чо такое, Николай? Пишите проще и более кратко. Вместо того, чтобы сказать "ой, я ляпнул про id с дуру" Вы нам рассказываете о макаке с Бетховеном? | |
|
|
|
|
|
|
|
для: BinLaden
(20.01.2009 в 21:52)
| | Ну вот кратко:
<?
session_start();
$code = ... $_GET['code']:null;
$_SESSION['count'] ++;
if($_SESSION['count'] > 3)
{
sleep(3);
header("location: страница с вводом E-mail и обнулением переменной сессии");
exit();
}
$res = mysql_query("SELECT COUNT(*) AS cnt WHERE `code`='".$code."' ");
if(!mysql_result($res,0,'cnt'))
{
echo "Осталось попыток: ".(3 - $_SESSION['count']);
echo "Введите код активации: <form action='?' method='get'>...";
}
else
{
// здесь активация
| Тут можно в принципе и id солёный захэшировать... Кому охота будет ресурсы на такое тратить? | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 22:02)
| | ???
Письмо с подтверждением запросто может прийти, когда время сессии двадцать раз выйдет. | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 22:05)
| | Вообще я понимаю, что можно и заголовок подделать, чтоб сессию обнулить. Это просто принцип. А письмо тут не при чем. Попытки считаются с момента начала активации, а не с момента отправки письма.
PS маленько исправил, чтоб понятней. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 22:02)
| | > Ну вот кратко:
OK, а какое отношение этот код имеет к вопросу о хешировании идентификатора? | |
|
|
|
|
|
|
|
для: BinLaden
(20.01.2009 в 22:23)
| | Этот код имеет отношение к макаке с Бетховеном. Я же написал, что бороться с подбором можно другим, более радикальным способом, нежели пытаться запутать взломщика страшными случайными строками. А идентифицировать клиента все равно нужно по уникальному ключу, буде то id, E-mail или логин на худой конц... Лишь бы не повторялось. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 22:32)
| | > Этот код имеет отношение к макаке с Бетховеном
Понятно. Вы всё о своём. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 20:44)
| | Макаронные изделия на ушах мне не нужны. | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 20:29)
| | я лично сделал так...
/* Функция получения Соли */
function G_s($n=5)
{
$ch = 'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ1234567890.,*_-=+';
$key = '';
$c = strlen($ch) - 1;
while (strlen($key) < $n){$key .= $ch[mt_rand(0,$c)];}
return $key;
}
$md_p = md5(sha1($p));
|
получаю в бд
log pass salt
CerG 22e9cd68b6e09804e25c8a857d08a1a0 N+gGm
|
/* Получаем Id, под которым юзер добавился в базу */
$id = mysql_result(mysql_query("SELECT LAST_INSERT_ID()", $db), 0);
// Отправляю письмо со ссылкой на активацию
$key = G_s ().$md_p;
$message.='<br/>http://www.xxx.ru/reg.php?id='.$id.'&key='.$key.'<br/>';
|
получаю ссылку типа...
.php?id=36&key=xa1HC3049a1f0f1c808cdaa4fbed0e01649 b1
|
юзер по ссылке приходит на страницу активации в ней форма
введите ваше имя..получаем
$id=$_GET['log']; // 36
$ key=$_GET['key']; // N+gGm22e9cd68b6e09804e25c8a857d08a1a0
$repit_log=$_POST['login']; // CerG
выбираем из бд значение salt где $id=36
производим сравнение
$ key==$row['salt'].md5(sha1($_POST['log']));
если все нормально то регистрируем..
есть ли по этому какие-то мысли ??? | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 20:51)
| | Я так и не понял, где считается $p.... и зачем в письме светить id
В точке окончательного сравнения держат хеш ожидаемого параметра.
У Вас же наоборот, хеш идет через почту, а открытый параметр лежит в БД .
Вы полагаете, что если пять раз повторите mt_rand() - её результат случайнее станет? Отнюдь.
Пожалуй с мыслями всё. | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 21:00)
| | | |
|
|
|
|
|
|
|
для: Trianon
(20.01.2009 в 21:00)
| | Псевдослучайные генераторы в php вообще весёлая штука, как показывают исследования
http://www.xakep.ru/post/46797/default.asp | |
|
|
|
|
|
|
|
для: Axxil
(21.01.2009 в 10:53)
| | Потому что фактически ими, что микроскопом забивают гвозди. Вроде тяжелый, и вроде гвоздь входит, а что не по шляпку, ну так хорошего понемножку...
То, что понемножку хорошего в криптологии оборачивается в конечном итоге крахом, предпочитают не думать. Как Николай здесь.
Семейство функций rand изначально разрабатывалось вовсе не для того , чтобы получить одно случайное число, а для генерации последовательностей с приличной статистикой. И уж точно не для криптологических целей.
А что до microtime(), то источник-то идеологически правильный, если его всякими srand() не портить.
Но, понятное дело, слабенький - достаточное количество бит из него выжать тяжело. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 11:39)
| | >То, что понемножку хорошего в криптологии оборачивается в конечном итоге крахом, предпочитают не думать. Как Николай здесь.
Я предпочитаю думать не о том, как сделать код абсолютно криптостойким, вероятно это в принципе не возможно, а о том, что бы какими то другими мерами отбить охоту даже пытаться расшифровать информацию. Ведь согласитесь, если после трех неудачных попыток изменить этод код и начать процедуру сначала, вряд ли у кого возникнет идея использовать всяческий брутфорс и иже с ним. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 11:58)
| | Если делать эти попытки руками - да. Если скриптом - отнюдь.
Но отповедь моя не конкретно на тему активации, а вообще на отношение к. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 12:05)
| | >Если делать эти попытки руками - да. Если скриптом - отнюдь.
Вынужден не согласиться. Может Вы не заметили в примере моего кода вот этой строчки:
>Но отповедь моя не конкретно на тему активации, а вообще на отношение к.
А мои рассуждения как раз именно про оптимизации данной проблемы. То есть во главу угла поставлена не криптостойкость особонезначимого кода, а надежность защиты другими, более радикальными мерами. А по откношению к вопрос другой, там разумеется и совсем другой подход. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 12:19)
| | >>Если делать эти попытки руками - да. Если скриптом - отнюдь.
>Вынужден не согласиться. Может Вы не заметили в примере моего кода вот этой строчки: sleep(3);
Я заметил другое. Строка эта никогда не выполнится потому,
if($_SESSION['count'] > 3)
что $_SESSION['count'] никогда не будет определено.
Какой же дурак будет передавать идентификатор сессии в скрипт такой проверки? | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 12:33)
| | >Я заметил другое. Строка эта никогда не выполнится потому,
Вы не заметили еще и этого в следующем моем посте:
>Вообще я понимаю, что можно и заголовок подделать, чтоб сессию обнулить. Это просто принцип.
Я не говорил, что это рабочий код, я говорил про принцип, а сессия - первое что пришло на ум для наглядности. Но сам то принцип ограничения числа попыток имеет право на жизнь?
Мне всё таки этот способ кажэтся более надежным, нежели повышение криптостойкости. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 11:58)
| | Вот Вам пример последствий неряшливого отношения.
Автор скрипта активации применяет rand(0 при генерации крипточувствительной информации.
Владелец сайта, приделывает ко всем страницам (через php_prepend или руками) какую-нибудь рекламную фигню, в коде которой тоже применяется rand() , значение которого напрямую вылезает в URLе баннера.
И всё. Текущее состояние генератора rand() открыто. Следующее, которое идет в генерацию ключа - вычисляется безо всякого подбора. Не нужны три попытки.
Вы скажете - а не приделывай всякую фигню.
А я скажу - верно. Но возлагать вину на владельца сайта (а не автора скрипта) мне было б совестно. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 12:12)
| | >Следующее, которое идет в генерацию ключа - вычисляется безо всякого подбора. Не нужны три попытки.
Да, но есть ведь еще параметр, кроме rand(), и к тому же хэш. Всё же некоторые усилия потребуются. Я и клоню к тому, что бы сделать эти усилия экономически невыгодными. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 12:30)
| | >>Следующее, которое идет в генерацию ключа - вычисляется безо всякого подбора. Не нужны три попытки.
>Да, но есть ведь еще параметр, кроме rand(),
id пользователя известен.
unixtime известен.
>и к тому же хэш.
так а что хеш? Хеш ведь по ним вычисляется, а не наоборот? | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 13:03)
| | >id пользователя известен.
Oткуда? Это же новый, неактивированный пользователь... Другое дело, что он может быть вычислен с помощью разных ухищрений. А на это вычисление как раз и понадобятся усилия. Можно конечно зарегистрировать первого пользователя руками и подставить следующий id в скрипт, но это как раз и есть экономическая нецелесообразность. Вариант не идеальный, но вполне оправданный. Нужно ведь сначала вычислить алгоритм формирования этого хэша (если конечно это не открытый код). А можно ведь так:
<?
$code = (rand() % 2 == 0)?md5($id.rand()):md5(rand().$id());
| Уникальность не пострадает... | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 13:23)
| | Новый. Но число пользователей обычно известно, так что спрогнозировать номер следующего - не задача.
А даже если известно, то из серии можно пожертвовать одним живым емэйлом (т.е. создать одного пользователя честно) , остальные пойдут по нарастанию.
$code = (rand() % 2 == 0)?md5($id.rand()):md5(rand.$id());
Ввот эта страшная на первый взгляд конструкция основана на том, что очередное значение rand() - неизвестно. А в моем примере оно известно - см. предыдущий ответ. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 13:29)
| | Заметьте, Николай, Вы спорите уже просто по инерции.
А замените rand() на microtime() и всё. Уязвимость уйдет. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 13:32)
| | >Заметьте, Николай, Вы спорите уже просто по инерции.
Нет, я вовсе не спорю, я хочу разобраться до конца. А разве microtime() на много сложнее вычислить, зная время запуска скрипта? Все равно с 10, 20, 100-й попытки можно угадать, если дать возможность угадывать... Конечно microtime() лучше в данном контексте, глупо спорить. Но я всё таки не это имею ввиду, а сам принцип построения защиты. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 13:40)
| | Если есть ссылка, то рано или поздно тупым брутфорсом точно можно активировать аккаунт.
Но если ввести пару id - хеш и ограничить число попыток активации для данного id одним разом, то проблема просто перестанет существовать при любой функции составления кода активации.
Причём, понятно, что открытый id должен вычисляться непредсказуемо (не тупо последовательные целые числа), чтоб злоумышленник не смог превентивно убить все эти активационные ссылки. | |
|
|
|
|
|
|
|
для: Axxil
(21.01.2009 в 13:55)
| | >ограничить число попыток активации для данного id одним разом,
Это жестко
А смысл нашего спитча в том, что если хеш вычислим на основании известных данных, то даже это ограничение не спасет. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 14:05)
| | > Это жестко
почему?
Пользователю достаточно кликнуть по правильной ссылке, чтобы попытка засчиталась.
Я не могу представить ситуации, когда пользователю понадобится менять код ссылки (разве что когда в почтовом редакторе ссылки иногда бьются).
Но в таком случае обычно пишется про "скопируйте ссылку целиком в строку браузера".
Тогда 2-3 попытки. Точно хватит. Если нет, то contact support :)
> А смысл нашего спитча в том, что если хеш вычислим на основании известных данных, то даже это ограничение не спасет.
Если он 100% вычислим в пределах 2-3 попыток, тогда да. Но наличие в коде даже функции rand, даёт очень мало шансов на это, при условии что ещё надо id подобрать. | |
|
|
|
|
|
|
|
для: Axxil
(21.01.2009 в 14:09)
| | >Тогда 2-3 попытки. Точно хватит. Если нет, то contact support :)
в принципе - да. Порядка этого.
>> А смысл нашего спитча в том, что если хеш вычислим на основании известных данных, то даже это ограничение не спасет.
>
>Если он 100% вычислим в пределах 2-3 попыток, тогда да. Но наличие в коде даже функции rand, даёт очень мало шансов на это, при условии что ещё надо id подобрать.
Ну вот я привел пример в 21.01.2009 в 12:12 . | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 14:15)
| | Ну это на словах легко :)
Предлагаю тест. Максимально просто для начала.
http://www.kazuals.ru/test/test.php
Здесь показывается сгенерированное случайное число в каком-то диапазоне.
Потом генерируется хеш для случайного числа:
и записывается в секретный файл.
Далее. Тут предлагается этот самый хеш ввести:
http://www.kazuals.ru/test/test1.php
Одна попытка, если хеш неугадан, то файл стирается и всё сначала.
Задача: скопировать сюда фразу, которая выводится при удачном решении.
PS. Детям: просьба скриптами не ддосить. Это просто тест. | |
|
|
|
|
|
|
|
для: Axxil
(21.01.2009 в 14:53)
| | >Ну это на словах легко :)
Понятно, что на деле сложнее.
Так за дело и деньги платят :) | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 14:57)
| | Тогда вопрос снят :)
Просто у вас это звучало так, как будто это слишком просто. Вот я и засомневался, может на самом деле это раз плюнуть :) | |
|
|
|
|
|
|
|
для: Axxil
(21.01.2009 в 15:10)
| | Жалко что снят, я хотел повозиться...
Не могу я успокоится. Вот попробовал посчитать microtime(). Если кому интересно, вот так:
<?
session_start();
/*unset($_SESSION['a']);
unset($_SESSION['b']);
exit();*/
$_SESSION['a'] ++;
$a = microtime()."<br>";
//for($i=0;$i<100;$i++)
$e = 1+1;
$b = microtime();
$c = $a - $b;
$d = $_SESSION['b'];
if(!in_array($c,$d))
$d[] = $c;
$_SESSION['b'] = $d;
echo count($_SESSION['b'])."<br>";
echo $_SESSION['a'];
| Результаты не утешительны. Разброс без цикла
52/100
с циклом
59/100
что при такой погрешности одно и то же. Стоит ли говорить, что при увеличении числа попыток разброс увеличивается... Так что
>А замените rand() на microtime() и всё. Уязвимость уйдет.
вряд ли... Всё равно получается, что без ограничения числа попыток никуда не дется. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 15:58)
| | Николай, какой гениальный код. А что он делает? | |
|
|
|
|
|
|
|
для: BinLaden
(21.01.2009 в 16:34)
| | Саркастический смешок не уместен ))). Я по своему скудоумию решил выяснить, можно ли зная время начала работы скрипта (отправки запроса) путем непрерывной долбежки вычислить параметр microtime(), который предлагается использовать вместо рандома. И мне кажется это не такая уж сложная задача. | |
|
|
|
|
|
|
|
для: BinLaden
(21.01.2009 в 16:34)
| | - | |
|
|
|
|
|
|
|
для: BinLaden
(21.01.2009 в 16:34)
| | - | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 17:50)
| | дату-время в Unix-формате, уже предлагавшуюся здесь альтернативой, вполне можно и спрогнозировать.
Что до microtime() - задача понятна, но всё ж сперва может поглядеть, что возвращает эта функция, а потом уже писать код? | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 17:58)
| | Каюсь, грешен... Единичку забыл. Но результат не многим лучше С рефрешем - минута работы - 24 совпадения. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 18:19)
| | Вы не учитываете время на прохождение запроса от клиента на сервер.
не факт, что оно будет таким стабильным
Но в принципе, Вы правы.
Почему я и написал, что сильно много случайных бит из этого источника не выжать. | |
|
|
|
|
|
|
|
для: BinLaden
(21.01.2009 в 16:34)
| | Форум сегодня веселит не на шутку... | |
|
|
|
|
|
|
|
для: Axxil
(21.01.2009 в 10:53)
| | Переводчику этой статьи нужно выдернуть ... подставить по вкусу.
Я так понимаю, что строка "2-4. первое слагаемое (double) microtime() будет равно 0, либо 1, а второе — " в исходном смысле звучала как-то так:
2-4. первый множитель (double) microtime() находится в промежутке от нуля до единицы, а второй -
Такие ляпы серьезно подрывают доверие ко всему материалу. А жаль. | |
|
|
|
|
|
|
|
для: Trianon
(21.01.2009 в 12:19)
| | Это да... :(
Такие ненаучно-популярные издания как "Хакер" читают, в основном, брутально настроенные дети, так как и издаётся он для детей (не удивительно, раз издатель "геймланд"). А дети, как известно, в тонкости вникать не любят. Им надо готовый рецепт, который можно скопипастить. Поэтому особенно с переводами и не заморачиваются. Дети всё равно визжат от восторга.
Те кто действительно интересуется предметом сразу же идёт читать оригинал.
PS. Вообще, качество перевода у нас, к сожалению, в большинстве случаев ниже плинтуса. Так как профессионалов мало. А те кто переводят зачастую вообще не врубаются в то что переводят. Поэтому если хочешь быть в курсе событий, просто физически необходимо учить английский. | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 20:51)
| | Вот это делается проще:
<?
//$id = mysql_result(mysql_query("SELECT LAST_INSERT_ID()", $db), 0);
$id = mysql_insert_id();
| А вообще лично я ничего из этого не понял. Уникальности кода нет, вероятность подбора осталась... | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 21:04)
| | Добавил сравнение вверху.. | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 21:13)
| | Ключ генерируется случайным образом, не зависимо от всяких id, email и тд. Тобишь в генерации ключа эти параметры не учавствуют. При регистрации аккаунта, все записывается в бд и в поле для ключа записывается абсолютно составленный(рандомно) ключ(хешированный, возможно не один раз). А при активации сравнение идет по большому счету с ним. | |
|
|
|
|
|
|
|
для: AcidTrash
(20.01.2009 в 22:22)
| | >Ключ генерируется случайным образом, не зависимо от всяких id, email и тд.
Вот тут хоть и ничтожно маленький, но все же элемент случайного совподения присутствует. Для этого и id, из за этого и сыр-бор. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 22:35)
| | Вот тут хоть и ничтожно маленький, но все же элемент случайного совподения присутствует. Для этого и id, из за этого и сыр-бор.
Включить в составляющую рандома, например реальное время в UNIX - формате. | |
|
|
|
|
|
|
|
для: serjinio
(20.01.2009 в 21:13)
| | А про автора и забыли совсем... Резюме. Вот четыре варианта генерации ключа.
Первый предложенный.
<?
$code = md5($email.rand());
|
Недостатки:
1. Первый параметр ($email) за ранее известен спамеру, который попытается подобрать код активации
2. Этическая составляющая (вынос, хоть и сильно запрятанныой но все же, личной информации).
Второй:
<?
$code = md5($id.rand());
|
Недостатки:
1. Вероятность подбора остается, хотя и меньше чем в первом варианте.
Третий:
<?
$code = md5(date('U').rand());
|
Недостатки:
1. Вероятность подбора так же остается, так как время генерации кода можно плюс минус вычислить.
2. Если совсем придраться, то этот вариант еще и более ресурсоёмкий.
Собственно Ваш.
Недостатки:
1. Вероятность подбора остается, хоть и ничтожно мала.
2. Еще более ресурсоёмкий.
3. Решение неоптимально с точки зрения величины кода.
4. Самый большой недостаток - отсутствие уникальности и, как следствие, вынос на обзор информации - id.
Выводы.
1. Если использовать первые три варианта, то лучше воспользоваться функцией mt_rand();
<?
$code = md5($id.mt_rand(5,15));
|
2. Для более эффективной защиты ограничить количество попыток активации.
Хотя это попахивает параноей, но мелочей не бывает, лучше сразу всё предусмотреть.
ИМХО. | |
|
|
|
|
|
|
|
для: Николай2357
(20.01.2009 в 23:40)
| | Вы пока тут спорили,я кое-что изменил..
переделал ф-цию ,на более стабильную
<?/* Функция получения Соли */
function G_s($n,&$keyy)
{
$ch = 'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ1234567890';
$c = strlen($ch) - 1;
while (strlen($keyy) < $n){
$keyy .= $ch[rand(0,$c)];
}
return $keyy;
}
$keyy = '';
G_s(5,$keyy);
echo '<br>G_s-+-'.$keyy;
$key = $keyy.$md_p;
|
поменял
//$md_p = md5(md5($p));
на
$md_p = md5(sha1($p));
|
Выкинул с сылки ID получилось типа
.php?key=hFpIf6ddc6b3660d35b640095d068c339cc 7f
|
по этой ссылке юзер приходит на страницу активации своего акка,где его встречает формочка,с просьбой ввести свое имя по которому он регистрировался...
<?
if (isset($_GET['key'])){
echo '
Введте свой логин выбранный при регистрации .
<form action="'.$_SERVER['PHP_SELF'].'" method="post">
<input name="login" type="text" size="37" />
<input name="key" type="hidden" value="'.trim($_GET['key']).'" />
<input name="ok" type="submit" value="Подтвердить !" id="ok" />
</form>';
}
if (isset($_POST['ok']))
{
/* Устанавливаем соединение с БД */
include_once ('../config.php');//сonnect BD
/* Формируем SQL-запрос */
$SQL=mysql_query("SELECT `u_log`,`u_salt`,`u_pass`
FROM `users`
WHERE `u_log`='".trim($_POST['login'])."'",$db);
$rw = mysql_fetch_assoc($SQL);
if (($rw['u_salt'].$rw['u_pass']) == (trim($_POST['key'])))
echo '<br>Ну и ну...Имя настоящее ...!
делаем дальше проверки..
подтвержден ли данный логин ..
не истёкли срок активации ....
если все ОК пишем в базу..
если нет удаляем его из базы и пусть идет по новой... !<br>';
}
|
писал на скорую руку без проверок вх. переменных..ну как идея??? | |
|
|
|
|
|
|
|
для: serjinio
(21.01.2009 в 01:25)
| | Ну давайте опять всё по порядку.
Во первых, что бы получить случайную строку из пяти символов, не обязательно столько телодвижений. Всё гораздо проще:
<?
$ch = 'abcdefghijklmnopqrstuvwxyzABCDEFGHI JKLMNOPQRSTUVWXYZ1234567890';
echo substr(str_shuffle($ch),58);
|
Во вторых, это практически не активация учетной записи, а временный пароль.
Идея не плоха, к тому же это не велосипед.
Лично мне всё таки больше импонирует система автоматической активации, что бы прошел по ссылке из письма, и в дамках. | |
|
|
|
|
|
|
|
для: Николай2357
(21.01.2009 в 08:29)
| | Согласен,сейчас подумаю как все-таки сделать одной ссылкой | |
|
|
|
|
|
|
|
для: serjinio
(21.01.2009 в 11:31)
| | Ну вот добрался до комьютера...
вариант активации одной ссылкой с одним параметром....
<?
/* Соль */
// воспользовался кодом Николая....
$r_key= substr(str_shuffle('abcdef0123456789'),11);// Создадим код "Соли" того-же вида, что и md5-хэш
/* В базе данных у нас будет храниться md5-хеш пароля */
$p =$_POST['pass'];
$md_p = md5(sha1($p));
mysql_query("INSERT INTO `users` (`u_log`,`u_pass`,`u_salt`, ............VALUES ( '$r_key',......'$md_p')",$db);
if ($new == 'true')
{
/* Составляем "Ключ" для активации */
$u_key = $md_p.$r_key;
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Получаем ссылку на активацию
// .php?key='.$u_key.'" target="_blank">АКТИВИРОВАТЬ !</a>
// .php?key=c72f5359811af711f29b1fac7150042fed3 72
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Активируем.....
if (isset($_GET['key']))
{
/* Устанавливаем соединение с БД */
include_once ('../config.php');//сonnect BD
// Вырезаем соль...
$salt= substr(trim(htmlspecialchars($_GET['key'],ENT_QUOTES,'UTF-8')),32); // ed372
/* Формируем SQL-запрос */
$SQL=mysql_query("SELECT `u_log`,`u_salt`,`u_pass`,`u_activat`
FROM `users`
WHERE `u_salt`='$salt' AND `u_activat` = 0 ",$db);
if (mysql_num_rows($SQL) > 0 )
{
$rw = mysql_fetch_assoc($SQL);
echo '<br>Есть такой юзер..'.$rw['u_log'].' ! делаем дальше проверки..
был ли уже активирован данный логин ..
не истёкли срок активации ....
если все ОК пишем в базу..
если нет удаляем его из базы и пусть идет по новой... !<br>';
}
|
Длину соли можно сделать любую,вставить ее можно и в начало и в конец и хоть в середину .
она все равно выглядит как и код md5.....как фантазия работает.....
вроде работает..утром еще нормально протестирую...
..самое главное идея.. что скажите ..какие могут быть подводные камни... | |
|
|
|
|
|
|
|
для: serjinio
(22.01.2009 в 01:58)
| | >какие могут быть подводные камни...
Вернее было бы сказать - где тут вода, и есть ли она под камнями....
Если завтра будет время, я перепишу Ваш код, это проще будет, чем поэтапно объяснять. | |
|
|
|
|
|
|
|
для: serjinio
(22.01.2009 в 01:58)
| | Ну вот, я добрался до компа.
Ваши основные ошибки:
1. Вы пытаетесь усложнить жизнь хакеру, спрятав за "непроницаемую" стену пароль юзера. Скажите - зачем? Ведь суть задачи дать возможность активировать запись только тому, кто знает ключ к активации, а пароль юзер знает лучше Вас, и в ответном письме он ему совсем не нужен. Чего нельзя сказать о злоумышленнике, перехватившем это письмо каким нибудь хитрым трояном. Задача заключается в двух главных моментах.
а) Исключить возможность активации записи методом подбора или расшифровки кода.
б) Идентифицировать пользователя по этому самому коду.
По первому пункту. Есть два пути - генерация случайного кода, что оказалось не так уж и просто, и ограничение числа попыток активации. Я склоняюсь ко второму, но если хотите первый - пожалуйста.
Что бы потерялся смысл расшифровки, нужно сгенерировать действительно случайную строку, которую нельзя дешифровать, вычислив некоторые параметры. Лучшим способом, как выяснилось, является генерацуия на основе не псевдослучайных параметров, а на действительно случайных. Раз уж муссировался вопрос о функции microtime(), то вот так можно сгенерировать случайную строку, похожую на хэш:
<?
// Массив можно заполнить статически, просто жалко места и лень.
$arr_num = range("0","9");
$arr_let = range("a","f");
$arr = array_merge($arr_num,$arr_let);
$arr = array_merge($arr,$arr_let);
$arr = array_merge($arr,$arr_num);
$arr = array_merge($arr,$arr_let);
$arr = array_merge($arr,$arr_let);
$arr = array_merge($arr,$arr_let);
$arr = array_merge($arr,$arr);
$rand = microtime(1);
for($i = 0; $i < 32; $i++)
{
$key .= $arr[(round(($rand * 1000 - floor($rand * 1000)),2) * 100 )];
$rand = microtime(1);
}
echo $key;
| Но эта процедура не даст гарантии уникального кода, а для чистоты эксперимента он должен быть уникальным. По этому нужен параметр, который не повторится ни при каких обстоятельствах. Идеальным является id записи. А так как смысла расшифровки кода нет, то можно процедуру упростить.
<?
mysql_query("INSERT INTO `users`..."
$id = mysql_insert_id();
$arr_num = range("0","9");
$arr_let = range("a","z");
$arr = array_merge($arr_num,$arr_let);
$arr = array_merge($arr,$arr);
$arr = array_merge($arr,$arr_let);
$arr[] = "a";
$rand = microtime(1);
for($i = 0; $i < 10; $i++)
{
$key .= $arr[(round(($rand * 1000 - floor($rand * 1000)),2) * 100 )];
$rand = microtime(1);
}
$r_key= md5($id.$key);
mysql_query("UPDATE....... (...`r_key`, ............VALUES ( ...'$r_key',....')",
// Отправляем письмо
| В результате мы имеем уникальный и не поддающийся подбору хэш, по которому и можно идентифицировать юзера:
<?
$key = isset($_GET['key']):$_GET['key']?null;
if($key)
{
$key = (get_magic_quotes_gpc())?mysql_escape_string(stripslashes($key)):mysql_escape_string($key);
$SQL=mysql_query("SELECT `u_log`,`u_salt`,`u_pass`,`u_activat`
FROM `users`
WHERE `r_key`='$key' ",$db);
if (mysql_num_rows($SQL) > 0 )
{
$rw = mysql_fetch_assoc($SQL);
echo '<br>Есть такой юзер..'.$rw['u_log'].' ! делаем дальше проверки..
был ли уже активирован данный логин ..
не истёкли срок активации ....
если все ОК пишем в базу..
если нет удаляем его из базы и пусть идет по новой... !<br>';
}
| Вот и вся недолга. Только намудрил я маленько, можно наверное оптимизировать, просто мне ближе вариант с попытками. | |
|
|
|
|
|
|
|
для: Николай2357
(22.01.2009 в 13:48)
| | >Раз уж муссировался вопрос о функции microtime(),
В аспекте разового вызова, но никак не повторения в цикле.
Понятно, что никакой случайной составляющей повторные вызовы не привнесут. | |
|
|
|
|
|
|
|
для: Trianon
(22.01.2009 в 16:21)
| | Почему? я проверял, разница есть и вполне существенная. Две последних цифры очень даже прилично скачут. | |
|
|
|