我通过SonataAdminBundle和SonataMediaBundle使用Symfony 4(更精确的4.1)。
这是我的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
然后,即使我已被认证为ROLE_SUPER_ADMIN
,我也总是得到AccessDeniedException。
该错误发生在vendor/sonata-project/media-bundle/src/Controller/MediaController.php
中的downloadAction
和viewAction
中。我一直在研究源代码,但找不到引发异常的原因。
答案 0 :(得分:2)
经过研究,我找到了罪魁祸首并解决了问题。在这里,我想分享我的知识。
正如我在问题中提到的,异常是从以下位置抛出的:
vendor/sonata-project/media-bundle/src/Controller/MediaController.php
在方法downloadAction
和viewAction
中。满足以下条件:
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
的路由,因为sonata_media:
resource: '@SonataMediaBundle/Resources/config/routing/media.xml'
prefix: /admin/media
不会检查是否授予访问权限。
找到罪魁祸首之后,问题是选择哪种方法来解决问题
1)更改路由前缀:
security.yml
media
中声明的路径现在覆盖ROLE_ADMIN
,并且ROLE_SUPER_ADMIN
和security.yml
可以访问路由。
缺点:如果要在管理员之外公开媒体怎么办?还有其他角色应该能够访问它们呢?
2)在access_control:
- { path: ^/media/, role: [ROLE_ADMIN, ROLE_SONATA_ADMIN] }
中声明新路径:
sonata_media:
# ...
contexts:
default: # the default context is mandatory
download:
strategy: sonata.media.security.connected_strategy
mode: http
# ...
现在,我们可以在管理员之外公开媒体。但是另一个问题仍然存在:如果其他角色需要访问媒体怎么办?
3)在SonataMedia的配置中配置另一种下载策略:
access_control:
# ...
- { path: ^/media/, role: [IS_AUTHENTICATED_FULLY, IS_AUTHENTICATED_REMEMBERED] }
# ...
并调整路径:
<Grid>
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Customers}">
<DataGrid.Columns>
<DataGridTextColumn Header="Name" Binding="{Binding Name}" />
<DataGridTextColumn Header="Name" Binding="{Binding Surname}" />
<DataGridTextColumn Header="Name" Binding="{Binding Age}" />
</DataGrid.Columns>
<DataGrid.ItemContainerStyle>
<Style TargetType="{x:Type DataGridRow}">
<EventSetter Event="MouseDown" Handler="DataGridRow_MouseDown" />
</Style>
</DataGrid.ItemContainerStyle>
</DataGrid>
</Grid>
现在,每个登录用户都可以访问媒体。这个解决方案对我有用。
但是,这并不是万能的菜谱。请查看官方文档中的security一章,以获取更多详细信息。