首页 > 解决方案 > Symfony4 安全中的两种认证方式

问题描述

我想在我的应用程序中使用两种身份验证方法。

一个用于实体用户,另一个(管理员)使用纯文本。

很简单。

因此,当我配置 security.yaml 时,我指定了提供程序:

security:
    providers:
        user:
            entity:
                class: App\Entity\User
                property: username
        in_memory: 
            memory: 
                users:
                    admin:
                        password: admin
                        roles: 'ROLE_ADMIN'

    encoders:
        App\Entity\User: bcrypt
        Symfony\Component\Security\Core\User\User: plaintext

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        admin: 
            provider: in_memory
            pattern: ^/admin/
            guard:
                provider: in_memory
            form_login:
                login_path: admin_login
                check_path: admin_login
            logout:
                path: /admin/logout
                target: /
        default:
            provider: user
            anonymous: ~
            guard:
                provider: user
            form_login:
                login_path: login
                check_path: login
                default_target_path: login_redirect
                use_referer: true
            logout:
                path: /logout
                target: /

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

并返回错误:

In GuardAuthenticationFactory.php line 121:

  Because you have multiple guard configurators, you need to set the "guard.e  
  ntry_point" key to one of your configurators ()     

然后,如果我必须设置guard.entry_point,我需要做这样的事情:

admin:
    entry_point: app.form_admin_authenticator
main:
    entry_point: app.form_user_authenticator

因此,如果我不明白,我需要像这样配置一个身份验证侦听器:https ://symfony.com/doc/current/components/security/authentication.html (顺便说一句,这个特定的帮助页面非常模棱两可且不完整)

有必要吗?对于我的目的来说,这似乎太复杂了

标签: symfonysymfony4

解决方案


我遇到了这个特殊的错误。我的情况可能会有所不同,但我也有类似的需求,需要根据应用程序的入口点使用不同的身份验证策略进行身份验证。

您的配置不包括的一件事是对任何 Guard Authenticator 对象的引用。有关这些对象所扮演的角色以及如何定义它们的介绍,请参阅此文档。Symfony 的安全包非常复杂,我发现使用 Guard Authenticators 使我的用例的过程变得简单得多。

security.yaml这是一个引用两个不同身份验证器的配置示例。配置entry_point告诉 Symfony先尝试哪一个,因为在我的特殊情况下,否则 Symfony 将不知道首先将哪种身份验证策略应用于传入请求。

security:
    providers:
        user:
            id: App\My\UserProviderClass

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            logout:
                path: app_logout

            guard:
                entry_point: App\My\MainAuthenticator
                authenticators:
                    - App\My\MainAuthenticator
                    - App\My\OtherAuthenticator

Custom Guard Authenticators包含一个名为supports. 此方法将传入请求作为其唯一参数,并根据是否应将给定身份验证器应用于传入请求返回 true 或 false。一种常见的做法可能是检查请求的 Symfony 路由名称(由控制器定义),或者可能是请求的完整 URI。例如:

    /**
     * Does the authenticator support the given Request?
     *
     * If this returns false, the authenticator will be skipped.
     *
     * @param Request $request
     *
     * @return bool
     */
    public function supports(Request $request): bool
    {
        $matchesMyRoute = 'some_route_name' ===
            $request->attributes->get('_route');

        $matchesMyUri = '/path/to/secured/resource' ===
            $request->getUri();

        return $matchesMyRoute || $matchesMyUri;
    }

您可以想象,如果在同一个应用程序中存在多个 Guard Authenticator,则很可能只是希望它们应用于某种类型的请求,无论区分是基于应用的身份验证类型(例如,标头使用 API 密钥与有状态会话 cookie),差异是否更多地与被命中的特定路由有关,或者可能是多种因素的组合。

在这种情况下,告诉 Symfony 首先尝试哪个 Guard Authenticator 可能对您的安全策略很重要,或者可能会对性能产生影响。例如,如果您有两个身份验证器,一个必须访问数据库来验证有状态会话,但另一个可以无状态地验证请求的身份验证,例如。通过验证 JWT 的签名,您可能希望首先运行 JWT 身份验证器,因为它可能不需要往返数据库来验证请求。

请参阅这篇文章以获得更深入的解释:https ://symfonycasts.com/screencast/symfony-security/entry-point


推荐阅读