#php
#php
Вопрос:
Задача состоит в том, чтобы защитить вызывающие методы общедоступного контроллера; нам нужно проверить, является ли пользователь администратором или нет перед вызовом.
class AdminController {
final public function __call($name, $arguments) {
if (!Auth::isAuth()) {
$User = UserFactory::loadById(Auth::getUserId());
if (!$User->isAdmin()) {
throw new ForbiddenException();
}
}
return call_user_func_array(array($this, $name), $arguments);
}
}
class AdminCategoryController extends AdminController {
public function view() { //__call() won't be called bacause it is public method
}
}
Мы можем использовать волшебный __call()
метод, но нам нужно, чтобы все методы были private
.
Другой способ, который я вижу, — определить final public __construct()
at AdminController
и поставить там проверку $User-> isAdmin()…
Есть еще идеи?
Спасибо.
Ответ №1:
Создайте новый метод в вашем базовом контроллере ( BaseController
), вызываемый isSecure()
:
public function isSecure() {
return false;
}
Затем в вашем контроллере, который должен быть безопасным ( AdminBaseController
), переопределите метод с помощью:
public function isSecure() {
return true;
}
AdminBaseController
распространяется BaseController
и AdminCategoryController
должен расширяться AdminBaseController
.
Затем в любой момент вы можете вызвать $Controller->isSecure()
любой контроллер, чтобы выяснить, должен ли он быть безопасным или нет.
Итак, в вашем коде отправки вы могли бы использовать что-то вроде этого (очевидно, требуется рефакторинг):
if($Controller->isSecure()) {
if (!Auth::isAuth()) {
$User = UserFactory::loadById(Auth::getUserId());
if (!$User->isAdmin()) {
throw new ForbiddenException();
}
} else {
$Controller->view();
}
}
Комментарии:
1. Зачем нам нужно внедрять
isSecure
метод? Будучи дочерним элементомAdminController
= все методы вызываются безопасно. РеализацияisSecure()
метода в порядке, если у меня нет отдельных контроллеров для администратора / общественности. Кстати, мне кажется, что лучше определитьisSecure
в корневом контроллере, а затем определить constanctIS_SECURE
для каждого дочернего контроллера.2. Таким образом, ваш код отправки может проверять перед вызовом контроллера. Ваш диспетчер должен направлять пользователя к
InvalidLoginController
или чему-то подобному, а не к*AdminController
, если они не авторизованы. Я немного пересмотрел свой ответ, пока вы комментировали. Я предлагаю вам перехватывать не прошедших проверку подлинности пользователей на уровень выше контроллера в вашем коде отправки.3. Ага, понятно. Итак, проверка IsCallable в dispatcher позволит нам реализовать полнофункциональный ACL. Отлично!