Symfony:多个防火墙上下文-用户被转发到错误的上下文


Symfony: Multiple firewall contexts - User being forwarded to the wrong context

我有一个前端登录名(这是可选的),还有一个管理面板登录名,这是强制性的。

当用户转到fe_login时,他们可以登录到frontend上下文。这没关系!

当他们转到admin_login时,他们应该能够登录到admin上下文。这是好的

问题是,当我转到/admin时,我会被重定向到fe_login,而本应重定向到admin_login

这是我的security.yml:

security:
    encoders:
        App'FrontendBundle'Controller'UserController:
            algorithm: bcrypt
        App'AdminBundle'Controller'UserController:
            algorithm: bcrypt
        App'Entity'User:
            algorithm: bcrypt
    providers:
        administrators:
            entity: { class: AppEntity:User, property: username }
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        admin:
            pattern: ^/admin
            form_login:
                login_path: admin_login
                check_path: admin_auth
                csrf_provider: form.csrf_provider
            logout:
                path: admin_logout
                target: admin_login
        frontend:
            anonymous: ~
            form_login:
                login_path: fe_login
                check_path: fe_auth
                csrf_provider: form.csrf_provider
                always_use_default_target_path: true
                default_target_path: fe_landing
            logout:
                path: fe_logout
                target: fe_landing
        login:
            pattern: ^/admin/login
            anonymous: ~
        default:
            anonymous: ~
    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin, roles: [ROLE_ADMIN,ROLE_MANAGER,ROLE_DRIVER,ROLE_PARTNER] }

知道我做错了什么吗?

这是我的security.yml,但正如我所说,它是针对Symfony2.0的,也许你会发现一个提示。

security:
    encoders:
### ...
role_hierarchy:
    ROLE_ADMIN:       ROLE_USER
    ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
providers:
    fos_userbundle:
        id: fos_user.user_manager
    admin_adminbundle:
        id: custom_admin_manager_id
firewalls:
    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false
    admin:
        pattern: ^/admin/
        form_login:
            check_path:         /admin/check-login
            login_path:         /admin/login
            provider:           admin_adminbundle
            csrf_provider:      form.csrf_provider
            post_only:          true
            success_handler:    login_success_handler
            failure_handler:    admin_login_failure_handler
            username_parameter: login_username
            password_parameter: login_password
            remember_me:        false
        logout:
            path:               /admin/logout
            target:             /admin/login
        anonymous: true
    frontend:
        pattern: ^/
        form_login:
            check_path:         /frontend/check-login
            login_path:         /frontend/login
            provider:           fos_userbundle
            csrf_provider:      form.csrf_provider
            post_only:          true
            success_handler:    login_success_handler
            failure_handler:    login_failure_handler
            username_parameter: login_username
            password_parameter: login_password
        logout:
            path:               /frontend/logout
            success_handler:    logout_success_handler
        anonymous: true
access_control:
    - { path: ^/frontend/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
    - { path: ^/admin/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }

我不太确定原因,但您现在必须知道security.yml必须是一个非常清晰的文件,以避免错过配置(这将导致安全问题)

所以,关于你的文件:

  • 它错过了前端部分的模式键:我会添加pattern: ^/
  • 前端登录路径可以指定为后端登录路径
  • 你的规则让我觉得有些地方不对

这是一个你应该测试的版本:

security:
    encoders:
        App'FrontendBundle'Controller'UserController:
            algorithm: bcrypt
        App'AdminBundle'Controller'UserController:
            algorithm: bcrypt
        App'Entity'User:
            algorithm: bcrypt
    providers:
        administrators:
            entity: { class: AppEntity:User, property: username }
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        login_admin:
            pattern: ^/admin/login
            anonymous: ~
        admin:
            pattern: ^/admin
            form_login:
                login_path: admin_login
                check_path: admin_auth
                csrf_provider: form.csrf_provider
            logout:
                path: admin_logout
                target: admin_login
        login_frontend:
            pattern: ^/login # you should adapt this to your app
            anonymous: ~
        frontend:
            pattern: ^/
            anonymous: ~
            form_login:
                login_path: fe_login
                check_path: fe_auth
                csrf_provider: form.csrf_provider
                always_use_default_target_path: true
                default_target_path: fe_landing
            logout:
                path: fe_logout
                target: fe_landing
    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin, roles: [ROLE_ADMIN,ROLE_MANAGER,ROLE_DRIVER,ROLE_PARTNER] }

您有一些似乎不必要的防火墙。让我们简化您的防火墙配置:

firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    admin:
        pattern: ^/admin
        form_login:
            login_path: admin_login
            check_path: admin_auth
            csrf_provider: form.csrf_provider
        logout:
            path: admin_logout
            target: admin_login
        anonymous: ~
    frontend:
        pattern: ^/
        anonymous: ~
        form_login:
            login_path: fe_login
            check_path: fe_auth
            csrf_provider: form.csrf_provider
            always_use_default_target_path: true
            default_target_path: fe_landing
        logout:
            path: fe_logout
            target: fe_landing
access_control:
    # allow unauthenticated to access admin login
    - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    # restrict admin access
    - { path: ^/admin, roles: [ROLE_ADMIN,ROLE_MANAGER,ROLE_DRIVER,ROLE_PARTNER] }
    # allow unauthenticated to access front end login
    - { path: ^/fe/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
    # restrict front end access
    - { path: ^/fe, roles: ROLE_USER } # or whatever the role is of your frontend user
    # allow all other pages to be viewed by unauthenticated users
    - { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

此配置使得/fe下的所有页面都需要前端授权,/admin下的所有页都需要管理员授权。并且所有其他页面根本不受保护。你可以根据自己的意愿进行调整。

access_control的顺序很重要。一旦匹配了规则,它就不会尝试匹配任何其他条目。此配置应该能够正常工作,以便显示正确的登录名。但是,您似乎并没有为每个防火墙使用不同的用户提供程序。因此,当您登录时,应用程序将为两次登录使用相同的提供程序。这可能是你想要的,也可能不是,但我想我会指出这一点。如果您确实希望每个登录都有不同的用户提供程序,只需将provider: ProviderName添加到每个防火墙即可。