英文:
Symfony6 : App.User is null (Authenticated User is not saved) cause of token lost after redirection
问题
I am working in Symfony5.3 application (released in 2020 or 2021 I guess), and I have to take it over and upgrade its version to Symfony6.2.
Well, I am facing some problems during authentications, after calling app.user.username in my html.twig file I got: Impossible to access an attribute ("username") on a null variable.
Well, I see app.user is null even after a successful login, the User is not correctly set to app.
And I don't know what's missing, here is my code:
security.yaml
security:
providers:
database_users:
id: App\Security\UsersProvider
password_hashers:
App\Entity\Users:
algorithm: sha512
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: database_users
logout:
path: logout
target: /login
invalidate_session: true
custom_authenticators:
- App\Security\LoginFormAuthentificator
LoginForm
class LoginFormAuthentificator extends AbstractLoginFormAuthenticator
use TargetPathTrait;
public const LOGIN_ROUTE = 'login';
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $userProvider;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager,
UserProviderInterface $userProvider)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->userProvider = $userProvider;
}
...
...
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('researchGeneral'));
}
public function authenticate(Request $request): \Symfony\Component\Security\Http\Authenticator\Passport\Passport {
$encoder = new MessageDigestPasswordHasher('sha512', true, 5000);
$user = $this->userProvider->loadUserByUsername($request->request->get("username"));
if (!$user) {
throw new CustomUserMessageAuthenticationException('Invalid credentials.');
}
$verif = $encoder->verify($user->getPassword(), $request->request->get("password"), 'sha512');
if (!$verif) {
throw a CustomUserMessageAuthenticationException('Invalid credentials.');
}
return new SelfValidatingPassport(new UserBadge($request->request->get("username")));
}
SecurityController
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('researchGeneral');
}
// 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]);
}
It's not the full code of each file, but I presented the code snippet I believe are concerned by this.
[EDIT]
The exact problem is losing the access token after redirecting.
英文:
I am working in Symfony5.3 application (released in 2020 or 2021 I guess), and I have to take it over and upgrade its version to Symfony6.2.
Well, I am facing some problems during authentications, after calling app.user.username in my html.twig file I got : Impossible to access an attribute ("username") on a null variable.
Well, i see app.user is null even after successful login, the User is not correctly set to app.
And I don't know what's missing, here is my code:
security.yaml
security:
providers:
database_users:
id: App\Security\UsersProvider
password_hashers:
App\Entity\Users:
algorithm: sha512
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: database_users
logout:
path: logout
target: /login
invalidate_session: true
custom_authenticators:
- App\Security\LoginFormAuthentificator
LoginForm
class LoginFormAuthentificator extends AbstractLoginFormAuthenticator
use TargetPathTrait;
public const LOGIN_ROUTE = 'login';
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $userProvider;
public function __construct(EntityManagerInterface $entityManager, UrlGeneratorInterface $urlGenerator, CsrfTokenManagerInterface $csrfTokenManager,
UserProviderInterface $userProvider)
{
$this->entityManager = $entityManager;
$this->urlGenerator = $urlGenerator;
$this->csrfTokenManager = $csrfTokenManager;
$this->userProvider = $userProvider;
}
...
...
public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $providerKey): ?Response
{
if ($targetPath = $this->getTargetPath($request->getSession(), $providerKey)) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('researchGeneral'));
}
public function authenticate(Request $request): \Symfony\Component\Security\Http\Authenticator\Passport\Passport {
$encoder = new MessageDigestPasswordHasher('sha512', true, 5000);
$user = $this->userProvider->loadUserByUsername($request->request->get("username"));
if (!$user) {
throw new CustomUserMessageAuthenticationException('Invalid credentials.');
}
$verif = $encoder->verify($user->getPassword(), $request->request->get("password"), 'sha512');
if (!$verif) {
throw new CustomUserMessageAuthenticationException('Invalid credentials.');
}
return new SelfValidatingPassport(new UserBadge($request->request->get("username")));
}
SecurityController
class SecurityController extends AbstractController
{
/**
* @Route("/login", name="login")
*/
public function login(AuthenticationUtils $authenticationUtils): Response
{
if ($this->getUser()) {
return $this->redirectToRoute('researchGeneral');
}
// 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]);
}
It's not the full code of each file, but I presented the code snippet I believe are concerned by this.
[EDIT]
The exact problem is losing the access token after redirecting.
答案1
得分: 0
在进行了大量研究后,我找到了问题所在。问题出现在Symfony\Component\Security\Http\Firewall\ContextListener中的hasUserChanged方法,它检测到了不希望的取消认证,因为我的userProvider中有一些错误。
无论如何,如果你遇到了这个问题,即app.user为null,或者在重定向后token发生变化,这绝对是由于你的组件(提供程序、实体、安全配置等)出现了故障,而很难有人能够为你进行调试。
英文:
Well, after a lot of research, i found the problem, it was the method hasUserChanged in Symfony\Component\Security\Http\Firewall\ContextListener it detected an undesirable de-authentication because i've some mistakes on my userProvider.
Anyway if you have encountered this problem, app.user null, or token changed after redirection is 100% due to malfunction of your components (provider or entity or security config or smth so) and it's really hard that someone can debug it for you.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论