Symfony2 — это веб-фреймворк, который появился совсем недавно. Соответственно, разработчики просто не успели написать к нему стоящую документацию. В одном из текущих проектов используется MongoDB, и ACL прикрутить нему можно, нужно всего лишь написать свой ACL-провайдер. Но я решил пойти своим путём. Итак, вот что примерно у нас получится:
Как видно, здесь аннотации route и template — стандартны и я не буду о них рассказывать. Нас же интересует собственная аннотация Permissions.
Ну что ж, приступим.
Для начала нужно создать класс аннотаций, который будет показывать ядру, что у нас теперь есть новая аннотация:
Таким образом, аннотация будет типа @Permissions(perm=«some_value»)
Следующим нашим шагом будет создания сервиса, в которым мы будем читать аннотации и выполнять какие-то действия, в зависимости от их значений.
Прошу заметить, что используем мы читалку аннотаций из доктрины. Но доктрина сегодня стала неотъемлемой частью symfony2.
Да. И последний шаг, но не менее важный. Теперь нам нужно зарегистрировать свой хук контролеера, или, если правильно назвать его: EventListener
Вот, собственно, и всё! Теперь наши аннотации готовы к использованию.
P.S. Для использования своих аннотаций в своих бандлах и контролерах нужно подключить только класс с аннотациями:
UPD: Сделал нормальную подсветку кода, спасибо sHinE
class DefaultController extends Controller { /** * Dashboard page. * @Permissions(perm="dashboard_view") * @Route("/", name="ITEDashboardBundle_index") * @Template() * @return array */ public function indexAction() {.......
Как видно, здесь аннотации route и template — стандартны и я не буду о них рассказывать. Нас же интересует собственная аннотация Permissions.
Ну что ж, приступим.
Для начала нужно создать класс аннотаций, который будет показывать ядру, что у нас теперь есть новая аннотация:
namespace SomeNameSpace\SomeBundle\Annotations; /** * @Annotation */ class Permissions { public $perm; }
Таким образом, аннотация будет типа @Permissions(perm=«some_value»)
Следующим нашим шагом будет создания сервиса, в которым мы будем читать аннотации и выполнять какие-то действия, в зависимости от их значений.
namespace SomeNamespace\SomeBundle\Annotations\Driver; use Doctrine\Common\Annotations\Reader;//Вот эта штука как раз и читает аннотации use Symfony\Component\HttpKernel\Event\FilterControllerEvent;//Подключаем нужный компонент ядра use SomeNamespace\SomeBundle\Annotations;//Юзаем свою аннотацию use SomeNamespace\SomeBundle\Security\Permission; //В этом классе я проверяю соответствие permission to user use Symfony\Component\HttpFoundation\Response; // В нашем примере я просто буду выводить 403, если нет доступа use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; class AnnotationDriver{ private $reader; public function __construct($reader) { $this->reader = $reader;//Получаем читалку аннотаций } /** * Это событие возникнет при вызове любого контроллера */ public function onKernelController(FilterControllerEvent $event) { if (!is_array($controller = $event->getController())) { //Выходим, если нет контроллера return; } $object = new \ReflectionObject($controller[0]);// Получаем контроллер $method = $object->getMethod($controller[1]);// Получаем метод foreach ($this->reader->getMethodAnnotations($method) as $configuration) { //Начинаем читать аннотации if(isset($configuration->perm)){//Если прочитанная аннотация наша, то выполняем код ниже $perm = new Permission($controller[0]->get('doctrine.odm.mongodb.document_manager')); $userName = $controller[0]->get('security.context')->getToken()->getUser()->getUserName(); if(!$perm->isAccess($userName,$configuration->perm)){ //Если после проверки доступа нет, то выдаём 403 throw new AccessDeniedHttpException(); } } } } }
Прошу заметить, что используем мы читалку аннотаций из доктрины. Но доктрина сегодня стала неотъемлемой частью symfony2.
Да. И последний шаг, но не менее важный. Теперь нам нужно зарегистрировать свой хук контролеера, или, если правильно назвать его: EventListener
# SomeBundle\config\services.yml services: some_annotation_driver: class: SomeNamespace\SomeBundle\Annotations\Driver\AnnotationDriver #Указываем класс tags: [{name: kernel.event_listener, event: kernel.controller, method: onKernelController}] #Указываем по какому событию вызывать этот сервис arguments: [@annotation_reader] # Передаём annotation_reader в конструктор нашего сервиса
Вот, собственно, и всё! Теперь наши аннотации готовы к использованию.
P.S. Для использования своих аннотаций в своих бандлах и контролерах нужно подключить только класс с аннотациями:
namespace SomeNamespace\SomeBundle\Controller; use SomeNamespace\SomeBundle\Annotations\Permissions; /** * Dashboard controller. * * @Route("/dashboard") */ class DefaultController extends Controller { /** * Dashboard page. * @Permissions(perm="dashboard_view") * @Route("/", name="ITEDashboardBundle_index") * @Template() * @return array */ public function indexAction() {...} }
UPD: Сделал нормальную подсветку кода, спасибо sHinE
