我认为我在Symfony安全组件方面达到了一定的极限。这是我的问题:我有两个防火墙来管理两个用户类型(具有两个不同的实体)的身份验证并访问网站的两个不同部分。我有第三部分来管理文件,上传文件……这些文件必须是私有的,并且两种用户类型都需要访问它。
所以我在security.yml中创建了多个提供程序:
providers:
# used to reload user from session & other features (e.g. switch_user)
core_user_provider:
entity:
class: Akyos\CoreBundle\Entity\User
property: email
platform_user_provider:
entity:
class: App\Entity\Platform\UserPlatform
property: email
file_manager_provider:
chain:
providers: [core_user_provider, platform_user_provider]
以及多个防火墙
防火墙: 开发人员: 模式:^ /(_(profiler | wdt)| css | images | js)/ 安全性:错误
core:
pattern: ^/(app|admin)/
context: shared
provider: core_user_provider
anonymous: lazy
guard:
authenticators:
- Akyos\CoreBundle\Security\CoreBundleAuthenticator
logout:
path: app_logout
target: 'home'
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
file_manager:
pattern: ^/(file-manager)
context: shared
provider: file_manager_provider
anonymous: lazy
guard:
authenticators:
- App\Security\FileManagerAuthenticator
logout:
path: file_manager_logout
target: 'home'
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
platform:
pattern: ^/(platorm_login|plateforme)
context: shared
provider: platform_user_provider
anonymous: lazy
guard:
authenticators:
- App\Security\PlatformAuthenticator
logout:
path: platform_logout
target: 'home'
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
main:
anonymous: lazy
因此,平台用户无法访问Core,而核心用户也无法访问Platform。但是,两个用户都需要访问File-manager,而无需重新登录。我不能将/ file-manager url放在Core或Platform防火墙下,因为另一个用户不会授予对其的访问权限。因此,我需要第三个防火墙来管理文件管理器访问。它使用将核心和平台用户分组的链提供程序。这也不起作用,因为如果Core用户通过Core防火墙进行了身份验证,则该用户未通过File-manager的身份验证,因此它将重定向到File-manager登录页面..如果用户登录了File-manager部分,则可以访问它,但是当它回到核心部分时,必须再次重新连接。
我尝试了几件事,但是最接近的解决方案是在防火墙上使用context选项,因此,当用户通过Core部分登录时,由于两个防火墙共享相同的上下文,因此可以访问File-manager部分而无需重新登录。这就是我想要的。但对于平台防火墙,我也需要它!因此,我还向其添加了相同的上下文选项,并且它可以正常工作,两种用户类型都可以访问File-manager,而无需再次登录:D但是,由于三个防火墙共享相同的上下文,因此核心用户可以访问Platform,反之亦然,并且破坏了所有的分离逻辑。.:'(
我需要一种方法来告诉安全组件“文件管理器防火墙与Core防火墙具有相同的上下文,文件管理器防火墙与Platform防火墙具有相同的上下文,但是Core和Platform防火墙没有共享相同的上下文”。像这样:
firewalls:
core:
context: core
file_manager:
context: [core,platform]
platform:
context: platform
main:
anonymous: lazy
我对此一无所获。也许无法完成,也许我必须创建自定义提供程序或身份验证程序才能对其进行破解。也许我可以不用Symfony,毕竟它只是php,所以我可以使文件管理器部分对每个人都可以访问(因此在主防火墙下),并添加一个侦听器,该侦听器将检查请求是否针对文件管理器,在会话中查找是否有以前的登录用户,请检查该用户是Core用户还是Platform用户,然后重定向(如果没有)...?没有Symfony功能的“主防火墙”页面(=认证为匿名)时,如何在会话中找到先前的Core或Platform用户?我还不知道如何实现这一目标。帮助吗?
谢谢
答案 0 :(得分:1)
我终于让3个提供程序和防火墙在它们之间共享了上下文。为了防止Core用户访问Platform,反之亦然,我添加了access_control:
- { path: ^/file-manager, roles: [ROLE_PLATFORM, ROLE_CORE] }
- { path: ^/core, roles: ROLE_CORE }
- { path: ^/plateforme, roles: ROLE_PLATFORM }
因此以403访问被拒绝错误结束。那不是我想要的行为,所以我还在核心和平台防火墙上都添加了“ access_denied_url”选项,以在良好的登录页面上重定向用户。由于上下文是共享的,因此用户已经被登录,因此在登录模板上,我检查了用户对象的实例,建议他先断开连接,然后再尝试访问此部分。
{% if instanceOf(app.user, 'App\\Entity\\PlatformUser') %}
You're already logged in Platform space, please <a href="{{ path('platform_logout') }}">log out</a> before access Core space.
{% else %}
You're already logged in as {{ app.user.username }}, <a href="{{ path('core_logout') }}">log out</a> or <a href="{{ path('core_index') }}">access core panel</a>.
{% endif %}
在各部分之间共享上下文有点困惑,这些部分除了访问文件管理器外不应该共享任何内容,但是没有用户可以访问其他部分。.