Symfony 4-安全性-将多个防火墙之间的上下文共享

时间:2020-06-11 15:34:08

标签: symfony symfony-security symfony-4.4

我认为我在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用户?我还不知道如何实现这一目标。帮助吗?

谢谢

1 个答案:

答案 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 %}

在各部分之间共享上下文有点困惑,这些部分除了访问文件管理器外不应该共享任何内容,但是没有用户可以访问其他部分。.