Возможно ли переключить большой PHP-бэкэнд с HTTP-аутентификации на сессионную систему - PullRequest
0 голосов
/ 16 ноября 2010

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

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

  1. Не катайся, если не знаешь точно, что делаешь
  2. Аутентификация на основе сеанса является действительно вовлеченным субъектом

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

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

Я смотрел на решения, использующие Zend Framework, CodeIgniter и CakePHP, - но все они предполагают определенный стиль кодирования (или это так кажется), и перспектива реорганизации всего моего кода, одним словом, снижается. (И кроме того, неэффективность включения одной из этих массивных платформ просто для аутентификации действительно меня теряет.)

Есть ли лучшее решение? Могу ли я изолировать класс аутентификации от одной из этих платформ? (Поскольку это всего лишь бэкэнд-сайт (закрыт), мне не нужно беспокоиться о регистрации или CAPTCHAS - или о каких-либо дополнительных функциях системы авторизации.)

Большое спасибо за ваше внимание.

Ответы [ 3 ]

2 голосов
/ 16 ноября 2010

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

Структура системы входа в систему на основе сеансов состоит в основном из трех частей:

  1. Сессияsetup
  2. Подтверждение безопасности
  3. Страница входа

Первые два в основном требуют наличия общего набора файлов, которые все ваших страницвключают.У большинства проектов есть такие;они делают такие вещи, как настройка соединения с базой данных и загружают служебные классы или функции.Итак, где-то в этом вам нужно добавить session_start().Теперь вы можете использовать сеансы ($_SESSION superglobal).

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

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

1 голос
/ 16 ноября 2010

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

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

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

0 голосов
/ 20 ноября 2010

Вдохновленный комментарием Хэмиша по моему вопросу, я узнал, что очень легко использовать класс Zend_Auth без необходимости использовать остальную часть фреймворка и без создания моего проекта «ZF way» - то есть с zf инструмент командной строки и шаблон MVC.

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

require_once('Zend/Db.php');
require_once('Zend/Auth.php');
require_once('Zend/Auth/Adapter/DbTable.php');
require_once('PasswordHash.php');
require_once('PasswordHash_Auth_Adapter_DbTable.php');

$auth = Zend_Auth::getInstance();
if ($auth->hasIdentity()) {
    echo 'Logged in...';
    $auth->clearIdentity();
    echo 'logged out.';
} else {
    // authenticate
    echo 'Authenticating...';
    $db_options = parse_ini_file('../zend_db.ini');
    $db = Zend_Db::factory('PDO_MYSQL', $db_options);
    $authAdapter = new PasswordHash_Auth_Adapter_DbTable($db);
    $authAdapter->setIdentity('test')->setCredential('test');
    $result = $auth->authenticate($authAdapter);
    if (!$result->isValid()) {
        echo 'invalid.';
    } else {
        echo 'valid.';
    }
}

PasswordHash_Auth_Adapter_DbTable.php - это пользовательская таблица Auth_Adapter_DbTable, использующая phpass для маскировки паролей, в основном скопированная из статьи Джонатана Стрита . Я также нашел статью Александра Песляка (которую я считаю создателем phpass), которая была очень полезна для широкого понимания хранения пользователей и паролей.

Стол users на данный момент крайне скучен:

CREATE TABLE `users` (
  `id` int(3) unsigned zerofill NOT NULL AUTO_INCREMENT,
  `user` varchar(60) NOT NULL,
  `pass` varchar(60) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `user` (`user`)
) ENGINE=MyISAM

Я вставил одного «тестового» пользователя с хэшем, сгенерированным phpass для пароля. В конечном итоге я планирую иметь форму входа, которая отправляет пользователя / пароль для аутентификации. На первый взгляд, этот метод (простая старая форма POST) кажется небезопасным, но я посмотрел на то, как работает форма входа в Facebook, и действительно я могу видеть свой пароль в виде открытого текста как часть данных формы после входа в систему - поэтому он не может быть это небезопасно (верно?).

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

Если я допустил какие-либо вопиющие ошибки, сообщите мне!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...