Использование Zend_Auth для защиты всех контроллеров
Как бы я глобально обезопасил все свои контроллеры (за исключением моего контроллера входа в систему), чтобы гарантировать безопасность моего приложения во всех точках (без скрытого бэкдора для вызовов ajax и т. Д.). Я думал, что мог бы поместить это в мой файл начальной загрузки, но это не так? Я пытаюсь избежать добавления какого-либо кода для каждого контроллера.
Предложения?
4 ответа
редактировать: это дополнение к ответу @singles.
Вы должны понимать, что есть 2 разные вещи. Auth и Acl. Auth сообщает вам, кто является пользователем, и вы можете, например, перенаправить пользователя, не имеющего Auth, на ваш контроллер входа в систему и установить идентификатор аутентификации после входа в систему. затем система Acl принимает решения "да / нет" на основе данных аутентификации (это может быть идентификатор пользователя или роль, хранящаяся в хранилище аутентификации).
Хорошее решение состоит в том, чтобы иметь 2 плагина контроллера (зарегистрированные в хорошем порядке на начальной загрузке, Auth затем Acl). Если вы не используете плагины контроллера, вам придется при необходимости вызывать проверку Acl на каждом контроллере. Если вам это всегда нужно, используйте плагины.
Реализовать preDispatch()
в вашем плагине Auth для установки, например, анонимного идентификатора, если у вас нет идентификатора, возвращаемого из Zend_Auth. Это фрагмент кода реального:
public function preDispatch(Zend_Controller_Request_Abstract $request)
{
$module = $request->getModuleName();
$controller = $request->getControllerName();
$action = $request->getActionName();
$auth = Zend_Auth::getInstance();
if (!$auth->hasIdentity()) {
// set a default anonymous identity
$auth->getStorage()->write(array('name' => 'anonymous','role' => 1,));
}
(...)
И для плагина контроллера Acl задача также в preDispatch()
, Вы можете запустить проверку ACL для каждого запрошенного URL (так для каждого пользовательского запроса, даже AJAX). Вот частичный фрагмент, так что это всего лишь пример того, как вы могли бы справиться с вещами:
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$controller = $request->controller;
$module = $request->module;
$action = $request->action;
// here you should code something nice retrieving you Zend_Acl object
// with some caching options maybe, building roles, ressources, etc
$this->_acl = $this->getAcl();
if (!$this->_acl->isCurrentUserAllowed($module,'see')) {
$auth = Zend_Auth::getInstance();
$identity = $auth->hasIdentity('identity')? $auth->getIdentity() : null;
if(isset($identity)) {
if($identity['name'] == 'anonymous') {
// WARNING: avoid infinite redirect loops on login page
if (!($request->getControllerName() == 'login'
&& $request->getActionName()=='login'
&& $request->getModuleName() == 'default')) {
$request->setControllerName('login')
->setActionName('login')
->setModuleName('default');
return;
(...)
и в этой системе последняя важная часть - это LoginController, где в случае успешного входа в систему вы должны инициировать запись идентичности:
(...)
$auth = Zend_Auth::getInstance();
Zend_Session::regenerateId();
$storage = $auth->getStorage();
$rowobject = $authAdapter->getResultRowObject(null,'passwd');
$storage->write((array)$rowobject);
(...)
Вы должны написать плагин ACL для этого и зарегистрировать его во фронт-контроллере. Если вы реализуете такую функциональность как плагин, у вас будет гибкость, чтобы использовать его в вашем следующем приложении - без необходимости расширения каждого контроллера из вашего пользовательского контроллера.
Ресурсы:
1. Плагины фронт-контроллера в Zend Framework - как плагины работают в ZF
2. Пример сценария Zend_Acl / Zend_Auth - одна из многих возможных реализаций плагина ACL.
3. Google - и множество других ресурсов
В одной из реализаций я сделал это, создав файл Auth.php в моем пути приложения. Затем я открыл каждый контроллер, который хотел защитить, и добавил строку
include_once APPLICATION_PATH . '/Auth.php';
в метод init() перед вызовом parent::init().
Что касается самого файла Auth.php, он в основном использует Zend_Auth для аутентификации. В случае успеха я сохраню личность пользователя для последующего использования в приложении
$this->view->assign('myIdentity', Zend_Auth::getInstance()->getIdentity());
В случае неудачи я перенаправляю на страницу входа и передаю некоторые параметры, чтобы страница входа знала, куда отправить меня после входа в систему.
Это не элегантное решение, но оно надежное, относительно быстрое и простое в реализации.
Ну, вам нужно иметь точку входа в вашу систему:)
Это может быть достигнуто путем расширения Zend_Controller_Action, скажем:
abstract class MyController extends Zend_Controller_Action {
public function preDispatch(){
// do the logic
}
}
И теперь каждому из ваших контроллеров нужно только расширить MyController, и вы в безопасности.