【问题标题】:Multiple entry points not working in Symfony 4.4多个入口点在 Symfony 4.4 中不起作用
【发布时间】:2020-05-10 01:02:02
【问题描述】:

我在网站上有 2 种用户类型:用户和供应商。这些类型中的每一种都将使用自己的登录表单。因此我决定在 security.yaml 中创建 2 个独立的防火墙:

security:
    encoders:
        App\Entity\Main\User:
            algorithm: bcrypt

        App\Entity\Main\Vendor:
            algorithm: bcrypt

    providers:
        users_provider:
            entity:
                class: App\Entity\Main\User
                property: email

        vendors_provider:
            entity:
                class: App\Entity\Main\Vendor
                property: email

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

        main:
            pattern:   ^/
            anonymous: ~
            provider: users_provider
            form_login:
                check_path: security_login
                login_path: security_login
                csrf_token_generator: security.csrf.token_manager
                csrf_parameter: _csrf_token
                csrf_token_id: authenticate
                use_referer: true
                target_path_parameter: go_to

            logout:
                path: security_logout


        vendor:
            pattern: ^/vendor/
            anonymous: ~
            provider: vendors_provider
            form_login:
                check_path: security_vendor_login
                login_path: security_vendor_login
                csrf_token_generator: security.csrf.token_manager
                csrf_parameter: _csrf_token
                csrf_token_id: authenticate
                use_referer: true
                target_path_parameter: go_to
            logout:
                path: security_logout

    access_control:
        - { path: ^/%locales%/login, roles: ['IS_AUTHENTICATED_ANONYMOUSLY'] }
        - { path: ^/%locales%/vendor, roles: ['IS_AUTHENTICATED_ANONYMOUSLY'] }
        - { path: ^/%locales%, roles: ['IS_AUTHENTICATED_ANONYMOUSLY'] }

用户 user-login.html.twig 的登录表单:

{% extends 'main/base.html.twig' %}

{% block content %}
    <form action="{{ path('security_login') }}"
          method="POST">
        <input type="text"
               id="email-field"
               class="form-control"
               name="_username"
               value="{{ form._username.vars.value }}">

        <input type="password" id="password-field" class="form-control"
               name="_password">

        <input type="hidden" id="csrf" name="_csrf_token"
               value="{{ csrf_token('authenticate') }}">
    </form>
{% endblock %}

供应商 vendor-login.html.twig 的登录表单:

{% extends 'main/base.html.twig' %}

{% block content %}
    <form action="{{ path('security_vendor_login') }}"
          method="POST">
        <input type="text"
               id="email-field"
               class="form-control"
               name="_username"
               value="{{ form._username.vars.value }}">

        <input type="password" id="password-field" class="form-control"
               name="_password">

        <input type="hidden" id="csrf" name="_csrf_token"
               value="{{ csrf_token('authenticate') }}">
    </form>
{% endblock %}

用于登录的路由在 routes.yaml 中定义:

security_login:
    path: /login
    controller: App\Controller\Main\SecurityController:loginAction
    methods: [GET, POST]

security_vendor_login:
    path: /vendor/login
    controller: App\Controller\Main\SecurityController:vendorLoginAction
    methods: [GET, POST]

以及SecurityController中的登录方法:

public function userLoginAction(Request $request)
    {
        $error = $this->authenticationUtils->getLastAuthenticationError();
        $lastUsername = $this->authenticationUtils->getLastUsername();

        $form = $this->formFactory->create(LoginForm::class, [
            '_username' => $lastUsername
        ]);

        return new Response(
            $this->twigService->render(
                'main/security/user-login.html.twig',
                [
                    'form' => $form->createView(),
                    'error' => $error,
                ]
            ),
            200
        );
    }

    public function vendorLoginAction(Request $request)
    {
        $error = $this->authenticationUtils->getLastAuthenticationError();
        $lastUsername = $this->authenticationUtils->getLastUsername();

        $form = $this->formFactory->create(LoginForm::class, [
            '_username' => $lastUsername
        ]);

        return new Response(
            $this->twigService->render(
                'main/security/vendor-login.html.twig',
                [
                    'form' => $form->createView(),
                    'error' => $error,
                ]
            ),
            200
        );
    }

当我使用 /login 路由时,我将作为用户成功登录。但是,如果我转到 /vendor/login 页面并提交电子邮件和密码,页面只会刷新而没有任何错误消息,并且我将不会通过身份验证。 在 var/log/dev.log 我看到了这个

[2020-01-23 17:12:05] security.INFO: Populated the TokenStorage with an anonymous Token. [] 

任何想法为什么会发生这种情况?

【问题讨论】:

    标签: symfony symfony4


    【解决方案1】:

    这是带有一些 cmets 的工作 security.yml。拥有正确的防火墙顺序很重要。在每个防火墙的模式定义中使用“^”也会破坏整个功能,即只有主防火墙可以工作。我不希望防火墙彼此共享“上下文”,所以对我来说这个参数不是必需的。如果您想在身份验证过程中执行某些操作,还可以为每个防火墙添加自定义用户检查器。

    security:
        encoders:
            App\Entity\Main\User: bcrypt
            App\Entity\Main\Vendor: bcrypt
    
        providers:
            users_provider:
                entity:
                    class: App\Entity\Main\User
                    property: email
    
            vendors_provider:
                entity:
                    class: App\Entity\Main\Vendor
                    property: email
    
        firewalls:
            dev:
                pattern: ^/(_(profiler|wdt)|css|images|js)/
                security: false
    
            vendor:
                pattern: /vendor
                anonymous: ~
                provider: vendors_provider
                # Custom user checker
                # https://symfony.com/doc/current/security/user_checkers.html
                # user_checker: App\Service\Main\VendorChecker
                form_login:
                    check_path: security_vendor_login
                    login_path: security_vendor_login
                    csrf_token_generator: security.csrf.token_manager
                    csrf_parameter: _csrf_token
                    csrf_token_id: authenticate
                    use_referer: true
                    target_path_parameter: go_to
                logout:
                    path: security_vendor_logout
                    target: /vendor
                remember_me:
                    secret: '%env(APP_SECRET)%'
                    lifetime: 1209600 # 2 weeks in seconds
                    path:     /
                    httponly: true
                    # Enable if you want that if you're authenticated in one firewall, you're automatically authenticated in another too
                    # Just use random but the same name in all firewalls you want to share the context with
                    # https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
                    # context: my_context
    
            main:
                pattern:   /
                anonymous: ~
                provider: users_provider
                # Custom user checker
                # https://symfony.com/doc/current/security/user_checkers.html
                # user_checker: App\Service\Main\UserChecker
                form_login:
                    check_path: security_login
                    login_path: security_login
                    csrf_token_generator: security.csrf.token_manager
                    csrf_parameter: _csrf_token
                    csrf_token_id: authenticate
                    use_referer: true
                    target_path_parameter: go_to
                logout:
                    path: security_logout
                    target: /
                remember_me:
                    secret: '%env(APP_SECRET)%'
                    lifetime: 1209600 # 2 weeks in seconds
                    path:     /
                    httponly: true
                    # Enable if you want that if you're authenticated in one firewall, you're automatically authenticated in another too
                    # https://symfony.com/doc/current/reference/configuration/security.html#firewall-context
                    # context: my_context
    
        access_control:
            - { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/vendor/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
            - { path: ^/, role: IS_AUTHENTICATED_ANONYMOUSLY }
            # Add your access control rules
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-01
      • 2014-11-11
      相关资源
      最近更新 更多