Symfony:防火墙,多个登录表单

11

我对symfony并不陌生,但我一直使用的是默认情况下防止针对两种不同用户类型进行身份验证的FOSUserBundle

我有两个实体,一个是Admins,另一个是Users。只有管理员才能在管理区域登录,而用户只能通过前端登录。

我遵循了以下文档:http://symfony.com/doc/2.1/book/security.html,其中还引导我查看了http://symfony.com/doc/2.1/cookbook/security/entity_provider.html

我的security.yml如下:

jms_security_extra:
    secure_all_services: false
    expressions: true

security:
    encoders:
        Symfony\Component\Security\Core\User\User: sha512
        Fm\AdminBundle\Entity\Admins: sha512
        Fm\MainBundle\Entity\Users: sha512

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
        chain_provider:
            chain:
                providers: [in_memory, admin]
        in_memory:
            memory:
                users:
                    user:  { password: userpass, roles: [ 'ROLE_USER' ] }
                    admin: { password: adminpass, roles: [ 'ROLE_ADMIN' ] }

        admin:
            entity: { class: Fm\AdminBundle\Entity\Admins, property: username }


    firewalls:
        dev:
            pattern:  ^/(_(profiler|wdt)|css|images|js)/
            security: false
            anonymous: true

        alogin:
            pattern:  ^/admin/login
            security: false
        login:
            pattern:  ^/login
            security: false
        secured_area:
            pattern:    ^/admin
            anonymous: false
            provider: chain_provider
            switch_user: true
            form_login:
                check_path: /admin/login_check
                login_path: /admin/login
            logout:
                path:   /admin/logout
                target: /admin
        members_area:
            pattern: ^/
            anonymous: false
            form_login: ~
            logout:
                path: /logout
                target: /
            #anonymous: ~
            #http_basic:
            #    realm: "Secured Demo Area"

    access_control:
        - { path: ^/admin/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/admin/, roles: ROLE_ADMIN }

在我的路由中,我按照文档定义了路由:(默认为/admin/login和/admin/login_check,因为我的主路由包含设置/admin)

_admin_login:
    pattern:   /login
    defaults:  { _controller: FmAdminBundle:Security:login }

_admin_login_check:
    pattern:   /login_check

我在浏览器中遇到的错误是:

无法找到路径“/admin/login_check”的控制器。也许您忘记在路由配置中添加匹配路由了?

堆栈跟踪告诉我:警告-由于缺少“_controller”参数,无法查找控制器

以及

错误-Symfony\Component\HttpKernel\Exception\NotFoundHttpException:无法找到路径“/admin/login_check”的控制器。也许您忘记在路由配置中添加匹配路由了?(未捕获的异常)位于/var/www/mysite.dev/symfony/app/bootstrap.php.cache第1419行


2
这是一个简单的正则表达式问题。在您的alogin防火墙中尝试使用“^/admin/login$”来防止login_check不在防火墙后面。编辑:登录当然也是一样的。 - dbrumann
那个“似乎”可以工作,但我相信在我的security.yml中有provider: chain_provider应该使我能够使用in_memory和admin提供程序(因为这是列出的内容)...如果我输入用户名admin和密码admin pass-它会重定向回登录屏幕,并显示“Bad Credentials”错误(目前数据库中没有用户)。有什么想法吗? - Justin
你确定你使用了正确的密码吗?应该是adminpass,而不是admin pass。另外,请检查一下Symfony安全组件的日志,看看是否一切都按预期工作。 - dbrumann
这是因为其中一个东西使用了sha512...我将其更改为单次迭代sha并对密码进行编码,现在它可以工作了...问题是,登录后它会将我重定向到domain.com/login而不是domain.com/admin。 - Justin
2个回答

12

要在Symfony 2XX中实现多重登录,请尝试以下代码:

Security.yml

security:
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
        Company\AngularBundle\Entity\User: plaintext
        Company\AngularBundle\Entity\Admin: plaintext

    role_hierarchy:
        ROLE_ADMIN:       ROLE_USER
        ROLE_SUPER_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]

    providers:
       users:
           entity: { class: CompanyAngularBundle:User, property: username }
       admin:
           entity: { class: CompanyAngularBundle:Admin, property: username }

    firewalls:
        admin_secured_area:
            pattern:   ^/admin
            anonymous: ~
            provider: admin
            form_login:
                login_path: /admin/login
                check_path: /admin/login_check
                default_target_path: /admin

        user_secured_area:
            pattern:   ^/
            anonymous: ~
            provider: users
            form_login:
                login_path: login
                check_path: login_check
                default_target_path: /home

路由配置文件

login_check:
    path: /login_check
admin_login_check:
   path: /admin/login_check

Twig文件

Action of login form should be like this
<form action="{{ path('login_check') }}" method="post">

Action of admin/login form should be like this
<form action="{{ path('admin_login_check') }}" method="post">

3
新手错误提示:请注意,如果您有^/和^/admin两个模式,更具体的模式(^/admin)必须放在较一般的模式^/之前,否则它不会优先匹配,因为^/仍然可以与^/admin匹配。这是我在我的应用程序中最终使其工作的方法,其中security.yml文件中也有一个^/模式,我没有意识到这就是yml处理正则表达式先后顺序的方式。 - Mick
你是怎么解决的?我在模式匹配方面遇到了问题。 - Dev M

4
问题在于,登录到“secured_area”防火墙后,您会被重定向到位于“members_area”防火墙之后的“/”页面。您不能使用“secured_area”的凭证访问“members_area”(至少默认情况下无法)。有关详细信息,请参阅http://symfony.com/doc/current/reference/configuration/security.html#reference-security-firewall-context
如果查看安全配置(http://symfony.com/doc/current/reference/configuration/security.html),您会发现form_login的default_target_path为“/”。只需将其更改为/admin即可。
security:
    ...

    firewalls:
    ...
        secured_area:
            pattern:    ^/admin
            ...
            form_login:
                check_path: /admin/login_check
                login_path: /admin/login
                default_target_path: /admin
            logout:
    ...

另一种方法是按照第一个链接中所述分享上下文 (http://symfony.com/doc/current/reference/configuration/security.html#reference-security-firewall-context)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接