У меня есть 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. []
Есть идеи, почему это происходит?
Вот рабочий security.yml с некоторыми комментариями. Важно правильно расположить брандмауэры. Также использование «^» в определении шаблона каждого брандмауэра нарушит всю функциональность, т.е. будет работать только основной брандмауэр. Я не хочу, чтобы межсетевые экраны разделяли «контекст» друг с другом, поэтому для меня этот параметр не нужен. Вы также можете добавить настраиваемую проверку пользователей для каждого брандмауэра, если хотите что-то сделать во время процесса аутентификации.