对于我的Symfony4应用,我想要:
听起来不错,每个都有一个专用的Guard身份验证器(尤其是登录后重定向,获取登录页面...)。我使用make
创建了保护文件样板,最终得到了下面的文件。
虽然在中层办公室的登录操作可以正常进行,但是当我尝试进入/admin
部分时,我仍然会遇到重定向循环。
日志显示,admin
防火墙在这里被正确地认为是很好的防火墙,但是尽管我将app_admin_login
设置为可以进行匿名访问,但它一直重定向到入口点。 admin/login
。为什么这样?
我当然想念这里,谢谢您的启迪。
[2019-02-13 11:46:39] request.INFO: Matched route "easyadmin". {"route":"easyadmin","route_parameters":{"_controller":"Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction","path":"/admin/","permanent":true,"scheme":null,"httpPort":8900,"httpsPort":443,"_route":"easyadmin"},"request_uri":"http://localhost:8900/admin","method":"GET"} []
[2019-02-13 11:46:39] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"admin","authenticators":1} []
[2019-02-13 11:46:39] security.DEBUG: Checking support on guard authenticator. {"firewall_key":"admin","authenticator":"App\\Security\\AdminLoginFormAuthenticator"} []
[2019-02-13 11:46:39] security.DEBUG: Guard authenticator does not support the request. {"firewall_key":"admin","authenticator":"App\\Security\\AdminLoginFormAuthenticator"} []
[2019-02-13 11:46:39] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /var/www/html/vendor/symfony/security-http/Firewall/AccessListener.php:51)"} []
[2019-02-13 11:46:39] security.DEBUG: Calling Authentication entry point. [] []
[2019-02-13 11:46:39] request.INFO: Matched route "app_admin_login". {"route":"app_admin_login","route_parameters":{"_route":"app_admin_login","_controller":"App\\Controller\\SecurityController::adminLogin"},"request_uri":"http://localhost:8900/admin/login","method":"GET"} []
[2019-02-13 11:46:39] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"admin","authenticators":1} []
[2019-02-13 11:46:39] security.DEBUG: Checking support on guard authenticator. {"firewall_key":"admin","authenticator":"App\\Security\\AdminLoginFormAuthenticator"} []
[2019-02-13 11:46:39] security.DEBUG: Guard authenticator does not support the request. {"firewall_key":"admin","authenticator":"App\\Security\\AdminLoginFormAuthenticator"} []
[2019-02-13 11:46:39] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /var/www/html/vendor/symfony/security-http/Firewall/AccessListener.php:51)"} []
[2019-02-13 11:46:39] security.DEBUG: Calling Authentication entry point. [] []
[2019-02-13 11:46:39] request.INFO: Matched route "app_admin_login". {"route":"app_admin_login","route_parameters":{"_route":"app_admin_login","_controller":"App\\Controller\\SecurityController::adminLogin"},"request_uri":"http://localhost:8900/admin/login","method":"GET"} []
[2019-02-13 11:46:39] security.DEBUG: Checking for guard authentication credentials. {"firewall_key":"admin","authenticators":1} []
[2019-02-13 11:46:39] security.DEBUG: Checking support on guard authenticator. {"firewall_key":"admin","authenticator":"App\\Security\\AdminLoginFormAuthenticator"} []
[2019-02-13 11:46:39] security.DEBUG: Guard authenticator does not support the request. {"firewall_key":"admin","authenticator":"App\\Security\\AdminLoginFormAuthenticator"} []
[2019-02-13 11:46:39] security.INFO: An AuthenticationException was thrown; redirecting to authentication entry point. {"exception":"[object] (Symfony\\Component\\Security\\Core\\Exception\\AuthenticationCredentialsNotFoundException(code: 0): A Token was not found in the TokenStorage. at /var/www/html/vendor/symfony/security-http/Firewall/AccessListener.php:51)"} []
[2019-02-13 11:46:39] security.DEBUG: Calling Authentication entry point. [] []
... Until max loop iteration number reached
security.yaml
security:
encoders:
App\Entity\Shop\User:
algorithm: argon2i
# 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\Shop\User
property: email
role_hierarchy:
ROLE_ADMIN: ROLE_USER
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
admin:
pattern: ^/admin
logout:
path: app_logout
guard:
authenticators:
- App\Security\AdminLoginFormAuthenticator
# logout_on_user_change: true
main:
pattern: ^/
anonymous: true
logout:
path: app_logout
guard:
authenticators:
- App\Security\LoginFormAuthenticator
# logout_on_user_change: true
# activate different ways to authenticate
# http_basic: true
# https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
# form_login: true
# https://symfony.com/doc/current/security/form_login_setup.html
# 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/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin, roles: ROLE_ADMIN }
- { path: ^/, roles: ROLE_USER }
AdminLoginFormAuthenticator
class AdminLoginFormAuthenticator extends AbstractFormLoginAuthenticator
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
private $request;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager, UserPasswordEncoderInterface $passwordEncoder)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->passwordEncoder = $passwordEncoder;
}
public function supports(Request $request)
{
$this->request = $request;
return ('app_admin_login' === $request->attributes->get('_route'))
&& $request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'email' => $request->request->get('email'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token'),
];
$request->getSession()->set(
Security::LAST_USERNAME,
$credentials['email']
);
return $credentials;
}
public function getUser($credentials, UserProviderInterface $userProvider)
{
$token = new CsrfToken('authenticate', $credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $this->entityManager->getRepository(User::class)->findOneBy(['email' => $credentials['email']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email could not be found.');
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid($user, $credentials['password']);
}
public function onAuthenticationSuccess(Request $request, TokenInterface $token, $providerKey)
{
$user = $token->getUser();
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('easyadmin'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_admin_login');
}
}
答案 0 :(得分:0)
由于@dbrumann向我指出了正确的方向,所以我设法做出了解决方法。 这只是一种解决方法,因为它没有说明重定向本身,而是避免。
我对此使用了AbstratcFormLoginAuthenticator::start()
方法:
/**
* Overrided to avoid redirection loop
* @param Request $request
* @param AuthenticationException|null $authException
*
* @return RedirectResponse|Response
* @throws \Exception
*/
public function start(Request $request, AuthenticationException $authException = null)
{
$url = $this->getLoginUrl();
// If URL different than login one, redirect to login one
if($url !== $this->urlGenerator->generate($request->attributes->get('_route'))) {
return new RedirectResponse($url);
}
// Render login page as a subrequest for this call only
else {
$path['_controller'] = SecurityController::class . '::adminLogin';
$subRequest = $request->duplicate([], null, $path);
return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST);
}
}
重定向到admin/login
页有效,调用了admin
防火墙,管理员保护响应,并且在管理部分成功登录了重定向。