我在设置新的Symfony应用程序时遇到了问题,我确定是与新的基于Authenticator的安全系统有关。
- 我安装了一个新的Symfony应用程序,版本为5.3.6。
- 安装了安全包
composer require symfony/security-bundle
(https://symfony.com/doc/current/security.html)。按照其中的所有步骤操作。 - 之后,我想根据https://symfony.com/doc/current/security/form_login_setup.html中的指导建立一个简单的登录表单。我执行了命令
php bin/console make:auth
,它生成了所有的文件并更新了我的security.yml,如往常一样。在这里,我注意到该命令没有生成Guard身份验证器(因为我理解它已被弃用),而是使用了新的身份验证管理器(https://symfony.com/doc/current/security/authenticator_manager.html)。 - 之后,我进入我的/login页面,输入凭据并提交表单。页面重新加载,但没有任何反应。没有错误消息,我还没有被认证。我没有做任何额外的步骤,因为它应该可以工作吧?至少旧的Guard身份验证器就是这样工作的。然而,这个新的身份验证系统似乎不起作用。我有什么遗漏吗?
我的文件:
LoginFormAuthenticator.php
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator{
use TargetPathTrait;
public const LOGIN_ROUTE = 'app_login';
private UrlGeneratorInterface $urlGenerator;
public function __construct(UrlGeneratorInterface $urlGenerator)
{
$this->urlGenerator = $urlGenerator;
}
public function authenticate(Request $request): PassportInterface
{
$email = $request->request->get('email', '');
$request->getSession()->set(Security::LAST_USERNAME, $email);
return new Passport(
new UserBadge($email),
new PasswordCredentials($request->request->get('password', '')),
[
new CsrfTokenBadge('authenticate', $request->get('_csrf_token')),
]
);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
return new RedirectResponse($targetPath);
}
// For example:
return new RedirectResponse($this->urlGenerator->generate('dashboard'));
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
}
SecurityController.php
class SecurityController extends AbstractController{
/**
* @Route("/login", name="app_login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
// if ($this->getUser()) {
// return $this->redirectToRoute('target_path');
// }
// 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', ['last_username' => $lastUsername, 'error' => $error]);
}
/**
* @Route("/logout", name="app_logout")
*/
public function logout()
{
throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
}
}
security.yml
security:
# https://symfony.com/doc/current/security/experimental_authenticators.html
enable_authenticator_manager: true
# https://symfony.com/doc/current/security.html#c-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
App\Entity\User:
algorithm: auto
# https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
custom_authenticator: App\Security\LoginFormAuthenticator
logout:
path: app_logout
# where to redirect after logout
# target: app_any_route
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#firewalls-authentication
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
die;
,提交表单后页面重新加载,这意味着我甚至没有到达authenticate()方法... - domskat/workspace/public/login
,但getPathInfo()只是/login
,所以supports()方法总是返回false
...有什么办法可以解决吗?编辑:我重写了supports()方法,并将getPathInfo()更改为getRequestUri(),这样就解决了...终于...我会写答案的。谢谢! - domskat