Symfony 3,一个应用程序中的 2 个防火墙

Posted

技术标签:

【中文标题】Symfony 3,一个应用程序中的 2 个防火墙【英文标题】:Symfony 3, 2 firewalls in one app 【发布时间】:2016-06-17 07:22:20 【问题描述】:

我在 symfony 3 中遇到了防火墙问题。从 3 天开始,我一直在努力解决这个问题。我已经阅读了文档并按照它做了所有事情,但是应用程序并没有像我预期的那样工作。

目标:所有页面(登录页面除外)都需要登录用户。如果用户没有登录,他应该被重定向到 /login 页面。就是这样。

根据本页:

http://symfony.com/doc/current/book/security.html http://symfony.com/doc/current/cookbook/security/form_login_setup.html

我创建了带有登录操作和表单的控制器。 login_path 和 check_path 使用相同的操作(根据文档)。可能 security.yml 中的某些内容是错误的,因为它无法正常工作。我的设置:

security:
providers:
    in_memory:
        memory:
            users:
                aaa:
                    password: aaa
                    roles: 'ROLE_ADMIN'
encoders:
    Symfony\Component\Security\Core\User\User: plaintext
firewalls:
    dev:
        pattern: ^/(_(profiler|wdt)|css|images|js)/
        security: false
    login_firewall:
        pattern:    ^/login
        anonymous: ~
#       form_login:
#           login_path: /login
#           check_path: /login
    secured_area:
        pattern:    ^/
        form_login:
            login_path: /login
            check_path: /login
            default_target_path: homepage
        logout:
            path:   /logout
            target: /login
#    access_control:
#        -  path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY 
#        -  path: ^/, roles: IS_AUTHENTICATED_FULLY 

我的登录操作:

<?php
/**
 * @Route("/login", name="login")
 */
public function loginAction(Request $request)

    $authenticationUtils = $this->get('security.authentication_utils');
    // get the login error if there is one
    $error = $authenticationUtils->getLastAuthenticationError();
    // last username entered by the user
    $lastUsername = $authenticationUtils->getLastUsername();

    return $this->render(
        'security/login.html.twig',
        array(
            // last username entered by the user
            'last_username' => $lastUsername,
            'error'         => $error,
        )
    );

?>

问题:

    使用此配置,我无法登录。请求使用登录操作,但系统不想对我进行身份验证。 如果我在 login_firewall 防火墙中取消注释 form_login,身份验证工作正常(我已登录),但我无法访问主页(系统将我重定向到登录页面,尽管我已通过身份验证。 我尝试使用 access_control,但行为与第 2 点相同。

请帮帮我。我确信这很简单,但我是 Symfony 的新手,我看不到它。

更新

感谢 Tobias Xy,我更正了 security.yml。工作版本:

security:
    providers:
        in_memory:
            memory:
                users:
                    smt:
                        password: smt
                        roles: 'ROLE_ADMIN'
    encoders:
        Symfony\Component\Security\Core\User\User: plaintext
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            form_login:
                login_path: /login
                check_path: /login
                default_target_path: /
            logout:
                path:   /logout
                target: /login
    access_control:
        -  path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY 
        -  path: ^/, roles: IS_AUTHENTICATED_FULLY 

【问题讨论】:

【参考方案1】:

修复:

我建议:

    完全删除 login_firewall。 在您的安全区域中允许匿名用户(匿名:~) 取消注释 access_control 部分(内容看起来不错)

让我知道它是否有效。

替代修复:

(这可能有效,但我不能 100% 确定)。

    将您的 check_path 更改为其他内容(例如 /check_login) 为 /check_login 创建一个空路由(类似于注销路由,此处描述:Security - Logging out) (确保这条新路径位于“secured_area”防火墙后面!)

一些解释

您的问题可能可以通过这个页面来解释:How to Build a Traditional Login Form。上面写着:

如果您使用多个防火墙并针对一个防火墙进行身份验证,则不会自动针对任何其他防火墙进行身份验证。不同的防火墙就像不同的安全系统。

这解释了您的一些问题:如果您在 login_firewall 中取消注释 form_login,您将仅对登录页面进行身份验证!一旦您转到另一个页面,您就不再经过身份验证,因为它是一个不同的安全上下文。

我不能 100% 确定您的问题 1,但它可能会发生,因为您的“check_path”也在防火墙 login_firewall 后面,而不是 secure_area。由于您的 login_firewall 中没有 form_login,因此无法识别提交的登录表单。

【讨论】:

感谢您的第一次修复。一切都很完美。你让我开心:)

以上是关于Symfony 3,一个应用程序中的 2 个防火墙的主要内容,如果未能解决你的问题,请参考以下文章

Symfony 3 - 登录时的防火墙监听器性能

symfony 2 在防火墙检查之前在事件监听器中添加角色

Symfony2 安全不同的防火墙不能正确重定向到登录

在共享 2 个环境的机器上运行 Symfony 3.2 项目中的作曲家安装

symfony 中的资产文件在防火墙后面?

Symfony 安全返回 401 响应而不是重定向