Я использую Symfony 4 (точнее 4.1) с SonataAdminBundle и SonataMediaBundle.
Это мой config/routes/sonata_media.yaml:
sonata_media_gallery:
resource: '@SonataMediaBundle/Resources/config/routing/gallery.xml'
prefix: /media/gallery
sonata_media:
resource: '@SonataMediaBundle/Resources/config/routing/media.xml'
prefix: /media
Если я запустил php bin/console debug:router, на выходе будут следующие маршруты:
sonata_media_gallery_index ANY ANY ANY /media/gallery/
sonata_media_gallery_view ANY ANY ANY /media/gallery/view/{id}
sonata_media_view ANY ANY ANY /media/view/{id}/{format}
sonata_media_download ANY ANY ANY /media/download/{id}/{format}
Первые два маршрута работают нормально, но когда я пробую два других маршрута, например:
http://localhost:8000/media/view/
http://localhost:8000/media/view/1/default
http://localhost:8000/media/download/1
http://localhost:8000/media/download/1/default
тогда я всегда получаю AccessDeniedException, даже если я аутентифицирован как ROLE_SUPER_ADMIN.
Ошибка возникает в vendor/sonata-project/media-bundle/src/Controller/MediaController.php, в downloadAction и в viewAction. Я копался в исходном коде, но не могу найти причину сгенерированного исключения.




После некоторого исследования я нашел виновника и решил проблему. Здесь я хочу поделиться своими знаниями.
Как я уже упоминал в вопросе, исключения были выброшены из:
vendor/sonata-project/media-bundle/src/Controller/MediaController.php
в методах downloadAction и viewAction. Это было следующее if-условие:
if (!$this->get('sonata.media.pool')->getDownloadSecurity($media)->isGranted($media, $this->getCurrentRequest())) {
throw new AccessDeniedException();
}
который присутствует в обоих методах. Это привело меня к vendor/sonata-project/media-bundle/src/Provider/Pool.php, а затем к vendor/sonata-project/media-bundle/src/Security/RolesDownloadStrategy.php. Я не смог найти там ни одной ошибки или проблемы, но это открыло мне глаза на другую позицию в моей собственной конфигурации:
access_control:
- { path: ^/admin/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] }
- { path: ^/.*, role: IS_AUTHENTICATED_ANONYMOUSLY }
Как я мог быть таким глупым? Путь /media не объявлен в security.yml, и к нему могут получить доступ неаутентифицированные пользователи. SonataMediaBundle требует по умолчанию ROLE_ADMIN или ROLE_SUPER_ADMIN для загрузки / просмотра носителя.
Маршруты для Gallery были доступны, потому что vendor/sonata-project/media-bundle/src/Controller/GalleryController.php не проверяет, разрешен ли доступ.
После обнаружения виновника возник вопрос, какой подход выбрать для решения проблемы.
1) Измените префикс маршрута:
sonata_media:
resource: '@SonataMediaBundle/Resources/config/routing/media.xml'
prefix: /admin/media
Объявленный путь в security.yml теперь охватывает media, а ROLE_ADMIN и ROLE_SUPER_ADMIN могут получить доступ к маршрутам.
Недостаток: что, если вы хотите выставить СМИ вне админа? А что, если другие роли должны иметь к ним доступ.
2) Объявите новый путь в security.yml:
access_control:
- { path: ^/media/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] }
Теперь мы можем выставлять средства массовой информации за пределами администратора. Но по-прежнему существует другая проблема: что, если другим ролям потребуется доступ к СМИ?
3) Настройте другую стратегию загрузки в конфиге для SonataMedia:
sonata_media:
# ...
contexts:
default: # the default context is mandatory
download:
strategy: sonata.media.security.connected_strategy
mode: http
# ...
и отрегулируйте путь:
access_control:
# ...
- { path: ^/media/, role: [IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED] }
# ...
Теперь каждый авторизованный пользователь может получить доступ к медиа. Это решение сработало для меня.
Однако это не универсальный рецепт. Пожалуйста, проверьте главу безопасность в официальной документации, чтобы получить более подробную информацию.
Омг, спасибо большое. Была такая же проблема в моем приложении, и я не обнаружил ошибку из-за поиска в неправильных файлах.