Несколько точек входа не работают в Symfony 4.4 - PullRequest
0 голосов
/ 23 января 2020

У меня есть 2 типа пользователей на сайте: пользователи и поставщики. Каждый из этих типов будет использовать собственную форму входа. Поэтому я решил создать 2 отдельных брандмауэра в security.yaml:

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'] }

Форма входа для входа пользователя в систему. 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 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 %}

Маршруты для входа в систему определены в route.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, тогда я буду успешно авторизован как пользователь. Однако, если я go перейду на страницу / vendor / login и отправлю адрес электронной почты и пароль, страница просто обновится без каких-либо сообщений об ошибках, и я не буду аутентифицирован. И в var / log / dev.log я вижу это

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

Есть идеи, почему это происходит?

1 Ответ

0 голосов
/ 24 января 2020

Вот рабочий файл 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...