Каков наилучший способ создания токена входа? Является ли этот метод аутентификации уязвимым для атаки?
Мне нужно внедрить токены входа в мое приложение на основе лития (PHP framework). Две причины:
Я хочу иметь функцию "запомнить меня".
Мне также нужен способ отслеживания логинов на сервере, чтобы я мог проверить аутентифицированных пользователей на сервере сокетов node.js следующим образом:
- Пользователь запрашивает страницу
- Сервер возвращает представление с токеном сеанса где-то в HTML
- Клиент JS считывает токен и отправляет его на сервер node.js в попытке установить соединение через веб-сокеты.
- Сервер получает запрос на соединение и проверяет маркер, отправленный ему с сервером PHP.
- Позволяет или отказывает соединение на основе результата.
Итак, это вопрос из двух частей, и просто чтобы убедиться, что я не являюсь идиотом, потому что безопасность на этом сайте имеет более высокий приоритет, чем обычно.
Является ли это разумным способом создания токена входа?
<?php
// String::hash() generates a sha512 (by default) hash.
String::hash(time() . $user['username']);
?>
Является ли система проверки подлинности веб-сокета я предлагаю разумно? Можете ли вы увидеть какие-либо проблемы, возникающие или какие-либо более эффективные способы сделать это?
Ответы
Ответ 1
Вы должны посмотреть класс RequestToken
в литии: http://li3.me/docs/lithium/security/validation/RequestToken::check()#source
Он обрабатывает CSRF-защиту и использует криптографически безопасные случайные токены, основанные на принципах, аналогичных приведенным выше, но с дополнительным уровнем защиты с помощью bcrypt, который может соответствовать любому количеству уникальных хэшей.
Ответ 2
Сначала вы должны изменить способ создания маркера входа. Хеш текущего времени, связанного с именем пользователя, далеко не сложно угадать; что является необходимым условием обеспечения безопасности. Есть много способов сделать это, важно то, что вы используете хороший источник случайности. Вы можете сделать:
list(,$token) = unpack('H*', openssl_random_pseudo_bytes(15, $safe));
$safe or die("unsafe source");
Общий метод, который вы используете, защищен только в том случае, если токен-носитель, который вы передаете, никогда не отправляется незашифрованным. Это означает, что каждый раз, когда он передается, он должен передаваться через SSL/TLS.
По-прежнему существует проблема, что вы случайно можете отправить токен в неправильное место, поэтому вы должны быть особенно осторожны, если какой-либо пункт назначения каким-то образом динамически генерируется (например, через какой-либо протокол обнаружения). Единственный способ избежать этой проблемы - использовать криптографию.
Ответ 3
Вы можете использовать функцию uniqid() для создания уникального идентификатора, чтобы увеличить вашу безопасность, а затем вы можете отказаться или использовать вместе с время.
<?php
String::hash(time() . uniqid() . $user['username']);
?>