Запись была отнесена к рубрике «Zend Framework» 14.05.2008, Ср в 03:34. Вы можете следить за общением по теме этой записи с помощью RSS 2.0 ленты. Вы можете оставить отзыв, или trackback с Вашего сайта.
Хороший подводный камень затаился в механизме работы ZF с плагинами когда вопрос авторизации разрешается именно с их помощью.
Общеизвестно, что кроме прочего плагины позволяют выполнять некий код до и после действия (action) контроллера. Именно тут и притаилась логическая бомба размеров чуть меньше среднего.
Обычно авторизация (определение возможности выполнения тех или иных деяний в зависимости от прав) помещается в Pre-обработчик:
class Application_Controller_Plugin_Auth extends Zend_Controller_Plugin_Abstract{
public function preDispatch(Zend_Controller_Request_Abstract $request){
/*
...
*/
}
}
конечно, можно было бы поместить проверку в обработчик dispatchLoopStartup, но если в ходе выполнения запроса будут вызываться несколько контроллеров и действий, то авторизация будет неполной
Код preDispatch представляет собой проверку возможности выполнения запрашиваемого действия с вынесением вердикта в виде перезаписи значений модуля, контроллера и действия. В случае когда перезапись нужно произвести как в случае отказа, так и благоприятного исхода и возникает неловкость.
Плагин Zend_Controller_Plugin_ErrorHandler, включенный по-умолчанию, регистрирует Post-обработчик и выполняет аналогичные действия с перезаписью значений модуля, контроллера и действия, но в случае возникновения исключений.
обычно в задачу этому плагину ставится отлов отсутствия вызываемого контроллера или действия, что можно рассматривать как ошибку №404, в то время как исключения внутри существующих действий как ошибку №500
Авторизация, в подавляющем большинстве конфигураций, пропустит нас к несуществующему действию. Однако обработчик ошибок чутко перенаправит на контроллер и действие (по-умолчанию error и error соответственно) по обработке ошибки, что в цикле диспетчеризации опять вызовет проверку авторизации. Если забыть прописать правила на доступ к контроллеру и действию обработки ошибок, мы будем повторно брошены на поиски несуществующего со всеми печальными последствиями: плагин ErrorHandler, почуяв мистический вызов себя второй раз, бросит неотлавливаемое уже никем (ясное дело, их отловом он и занимается) исключение и все будет потеряно.
можно обернуть в try…catch вызов Zend_Controller_Front::getInstance()->dispatch() чтобы ловить неотлавливаемое и там
Необходимо предотвратить натаптывание дорожки с граблями т.е. не давать коду авторизации перезаписывать значения модуля, контроллера и действия, если они ведут в место, где производится обработка ошибок.
Сделать это можно как прописыванием правил Zend_Acl для обработчика ошибок, так и проверкой на существование исключений за обработкой которого мы и обратились к некому контроллеру:
public function preDispatch(Zend_Controller_Request_Abstract $request){
if ($this->_response->isException()) return;
/*
...
*/
}
А зачем _обязательно_ переписывать при авторизации значения контроллера и так далее?
Ну, к примеру, если юзер, зарегистрирован, но потерял некое право (платный период закончился) что-либо делать в полной мере. Т.е. он по сути получает один и тот же ресурс (в терминах ACL), но под другой ролью. Но в целом вопрос правомерен, конечно - очень ограничивающее условие. Тут дело, скорее, в том, что следует следить и знать про возможность где-либо перезаписывать координаты модуль-контроллер-действие уже после того как приложение навострилось на обработку ошибок.
Есть ли эксепшены лучше проверять не getException(), а isException().
Верно, да, спасибо. Смотрел содержимое коллекции исключений и скопипастил :\. А так, Вы, разумеется, правы.
Хорошая заметка. Надо быть повнимательнее….