Intereting Posts
Как использовать функцию password_verify в PHP phpmyadmin работает нормально, но я не могу найти файл config.inc.php? Каков наилучший подход для создания динамических запросов (с использованием PHP + MySQL)? Добавление загружаемого изображения при запуске PHP-скрипта Как получить элемент из массива объектов PHP? Проблема с отправкой объекта JSON через POST в Google Gears В любом случае, чтобы определить, закрывает ли пользователь браузер с помощью php? написать php внутри оповещения javascript Блокирование входа пользователя с определенным уровнем разрешений, а затем отображение предупреждений, чтобы сообщить им, почему mysql не обновляется из php-формы preg_match все абзацы строки Как изменить значение скрытого файла, в соответствии с выбранным радио file_exists () возвращает false, но файл существует как я могу преобразовать frm php в c # или json (extjs) Когда использовать класс или функцию в PHP

Кодирование файлов cookie, чтобы их нельзя было подделать или читать и т. Д.

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

Я хочу закодировать их или обфускать их, чтобы их нельзя было читать или подделывать.

Каков наилучший способ сделать это?

Обновить:

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

Короткий ответ

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

Лучший способ сделать это

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

 $randomToken = hash('sha256',uniq_id(mt_rand(), true).uniq_id(mt_rand(), true)); 

Затем храните его в db рядом с пользователем и отправляйте cookie клиенту (я также предлагаю подписать маркер, а также предотвратить фальсификацию:

 $randomToken .= ':'.hash_hmac('md5', $randomToken, $serverKey); 

Теперь, когда вы проверяете, сначала проверьте, соответствует ли хэш:

 list($token, $hmac) = explode(':', $_COOKIE['remember_me'], 2); if ($hmac != hash_hmac('md5', $token, $serverKey)) { die('tampered token!'); } 

Оттуда просто найдите пользователя по токену. Если вы его найдете, зарегистрируйте этого пользователя.

Я также предлагаю изменить токен при каждом изменении пароля.

Чтобы ответить на ваш вопрос напрямую

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

Чтобы закодировать его, я бы использовал mcrypt для шифрования данных в файл cookie. Затем я сделал бы случайную соль и сохранил ее с пользовательской строкой, а затем подпишите зашифрованные данные с помощью hash_hmac используя эту уникальную соль. Таким образом, если кто-то перехватывает файл cookie и вычисляет ключ для склепа, вы все равно можете обнаружить недопустимый hmac, чтобы вы могли найти тамперы.

 function generateCredentialsCookie($user_id, $password) { $encrypted = encrypt($user_id.':'.$password, $secretkey); $salt = uniq_id(mt_rand(), true); $encrypted .= ':'.hash_hmac('sha256', $encrypted, $salt); storeSaltForUser($user_id, $salt); set_cookie('credentials', $encrypted); } function readCredentialsCookie() { $parts = explode(':', $_COOKIE['credentials']); $salt = array_pop($parts); $encrypted = implode(':', $parts); //needed incase mcrypt added `:` $raw = decrypt($encrypted, $secretkey); list ($user_id, $password) = explode(':', $raw, 2); if ($salt == getSaltForUser($user_id)) return array($user_id, $password); } else { return die('Invalid Cookie Found'); } } 

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

НЕ используйте длинные сеансы!

Вы должны сократить срок действия сеанса как можно ниже (я обычно использую 30-минутные сеансы, но некоторые сайты ниже). Время истечения срока действия после последнего использования, так что пока сайт активно используется, это не имеет значения.

Что касается того, почему не использовать длительную сессию, вот несколько минусов:

  • Созданы уязвимости DOS (Denial Of Service).

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

    • Пространство папок – каждый сеанс занимает один файл в одной папке. Самые популярные файловые системы замедлятся с большим количеством файлов в одной папке. Поэтому, если вы поместите 1 миллион файлов сеанса, чтение или запись в файл сеанса будет медленным (очень медленным). И сбор мусора (который очищает старые файлы) будет ОЧЕНЬ ОЧЕНЬ ОЧЕНЬ медленным (если он вообще будет работать).

  • Открываются уязвимости, связанные с захватом сеанса . Это связано с тем, что чем больше сеансов у вас открыто на сайте, тем легче будет угадать действительный идентификатор (благодаря атаке на день рождения ). Чем меньше сеансов у вас есть, тем труднее будет угадать действительный.

Скорее всего, другие, но это краткий обзор. Вместо длительных сеансов используйте подписанный токен mem-me, как описано выше. Вам будет намного лучше, и гораздо безопаснее …

Хранение пользовательских данных в файле cookie является неправильным способом. Вы должны использовать сеансы PHP . Единственное, что будет храниться на клиенте, будет идентификатор сеанса в простой cookie (что PHP будет обрабатывать для вас автоматически). Это уже зашифрованная строка.

PHP будет отслеживать данные пользователя на стороне сервера.

Это обеспечит желаемый эффект, который вы описали, оставаясь более безопасным, чем использование файлов cookie.

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

Пара методов:

Если пользователь выбирает «запомнить меня», просто установите перед инициализацией сеанса следующее.

 session_set_cookie_params(60 * 60 * 24 * 7); //save cookie session for 7 days 

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

Однако я бы порекомендовал первый вариант.

Соль печенья перед сохранением. Добавьте user-agent, ip, как вы хотите расширить безопасность.

 $cookie_to_save = sha1($pwd . $user_agent . $yourSalt); 

на автолог

 if($cookie_saved == sha1($pwd . $user_agent . $yourSalt) ok... 

Простое создание 16 или более криптографически безопасного случайного числа и сохранение этого в файле cookie. Нет необходимости в шифровании / расшифровке. Используйте его с ограниченным сроком действия, установленным на стороне сервера (не полагайтесь на MaxAge или Expires). Это сеансовый файл cookie.

Это очень безопасно, так как критическая информация не покидает сервер.

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

Для минимизации задержек загрузки и ответа сервера сохранение идентификатора пользователя, его роли и штампа создания файла cookie в защищенном файле cookie является допустимым вариантом. Для изъятия неверных запросов не требуется ни базы данных, ни кэша, и если идентификатор пользователя компактный, индекс будет небольшим и быстрее для поиска. Но не изобретайте свою собственную безопасную кодировку значений, если вы не знаете, что делаете.

Недостатком этого метода является то, что, если кто-то узнает ключ, он может кузнуть куки. Затем он может создавать файлы cookie с разными идентификаторами пользователей и получать доступ к своей учетной записи. Поэтому используйте этот метод, где риск ограничен и доступ к ключу хорошо контролируется. Специальным аппаратным устройством, выполняющим шифрование / дешифрование и скрывающим ключ, может быть решение. Но это в настоящее время необычно и дорого. Задержка может быть больше, чем поиск случайного идентификатора сеанса в кеше. Позднее это более простое и безопасное решение.

Использование открытых / закрытых ключей для обеспечения ценности в файле cookie может использоваться для защиты закрытого ключа. Но это намного сложнее, и латентность может быть сравнима с системой с простым случайным кэшированным идентификатором сеанса.

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