Пишу авторизацию, пользуясь MVC паттерном. Каждый контроллер отвечает за страницу, которую надо вывести (авторизован или форма входа). Как сделать саму проверку авторизации - понятно. Но как сделать ее на всех страницах сайта? В каждом новом контроллере писать условия? - но это повторы кода и мне кажется это не совсем правильно.
MVC подразумевает что имеется единая точка входа в приложение.
Именно в этой точке и должны проверяться такие вещи.
Т.е имеется класс Application, который дергает Router и определяет какой Controller\Action вызвать.
В Router в свою очередь должны существовать фильтры, один из которых может проверять авторизован ли пользователь
Да именно, одна точка входа. Там стоит роутер, который выводит запрашиваемый контент. В роутере писать проверку авторизованности? - как-то глупо, не находите?
В Router и делается такая проверка. По крайней мере в тех фрейморках которые я использовал. Можно конечно прописывать фильтры в контроллерах, но в итоге они все равно будут обрабатываться роутером.
Можно посмотреть как это реализованно в том же Laravel например. Имеются middleware, которые вызываются при старте приложения и после загрузки основных частей.
Router может определять группы роутов, для которых можно задать определенный набор middleware которые должны быть вызванны при обращении к этим роутам.
Т.е конкретно сам Router не занимается подобными вещами, он дергает внешние middleware, которые если нужно могут прервать выполнение скрипта.
Denormalization: То есть получается, если использовать роутер в качестве проверки авторизованности, то он будет обращаться к определенному контроллеру, который будет доступен только для авторизованных пользователей? Не много получается контроллеров?
Нет. Router должен проверять есть ли у роута\группы роутов какой-либо фильтр\middleware, и если есть, вызывать соответсвующий фильтр.
Т.е допустим у нас есть:
$router->post('users', ['uses' => 'UsersController@store', 'middleware' => 'auth']; (пример для Laravel)
'auth' определен как:
'auth' => 'Middleware\Authenticate.php'
В котором есть функция:
function handle($router, $next) {
$auth = // Сервис
if ($auth->isGuest())
return redirect('/login');
return $next($router);
}
Теперь, когда я обращаюсь к POST /users, то Router смотрит что у данного роута есть middleware -> auth, и вызывает этот Middleware.
Middleware в свою очередь проверяет авторизован ли пользователь, и если да, то выполнение продолжается. Если же пользователь не авторизован, то middleware прерывает цепочку, и возвращает юзеру редирект на вход.
Это что относится к реализации в Laravel.
У себя можно сделать проще:
Создаем базовый контроллер AuthenticatedContoller с интерфейсом MIddlewareInterface и методом:
public function handle($request)
{
}
В Router, или где там у вас создается экзепляр контролеллера проверяем:
if ($controller instanceof MiddlewareInterface)
{
$result = $controller->handle($request);
}
И дальше уже обрабатываем как угодно, можно кидать exception например.