登录用户仍然有一个空的会话symfony 5



我在使用 Symfony 5 登录后无法显示用户用户名,并且我发现用户登录后会话对象仍然为空,这是我的身份验证器.php文件

<?php
namespace AppSecurity;
use AppEntityUser;
use DoctrineORMEntityManagerInterface;
use SymfonyComponentHttpFoundationRedirectResponse;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentRoutingGeneratorUrlGeneratorInterface;
use SymfonyComponentSecurityCoreAuthenticationTokenTokenInterface;
use SymfonyComponentSecurityCoreEncoderUserPasswordEncoderInterface;
use SymfonyComponentSecurityCoreExceptionCustomUserMessageAuthenticationException;
use SymfonyComponentSecurityCoreExceptionInvalidCsrfTokenException;
use SymfonyComponentSecurityCoreSecurity;
use SymfonyComponentSecurityCoreUserUserInterface;
use SymfonyComponentSecurityCoreUserUserProviderInterface;
use SymfonyComponentSecurityCsrfCsrfToken;
use SymfonyComponentSecurityCsrfCsrfTokenManagerInterface;
use SymfonyComponentSecurityGuardAuthenticatorAbstractFormLoginAuthenticator;
use SymfonyComponentSecurityGuardPasswordAuthenticatedInterface;
use SymfonyComponentSecurityHttpUtilTargetPathTrait;
class AuthAuthenticator extends AbstractFormLoginAuthenticator implements
PasswordAuthenticatedInterface
{
use TargetPathTrait;
private $entityManager;
private $urlGenerator;
private $csrfTokenManager;
private $passwordEncoder;
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)
{
return 'app_login' === $request->attributes->get('_route') &&
$request->isMethod('POST');
}
public function getCredentials(Request $request)
{
$credentials = [
'matricule' => $request->request->get('matricule'),
'password' => $request->request->get('password'),
'csrf_token' => $request->request->get('_csrf_token')
];
$request
->getSession()
->set(Security::LAST_USERNAME, $credentials['matricule']);
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(['matricule' => $credentials['matricule']]);
if (!$user) {
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException(
'The Member Matricule could not be found.'
);
}
return $user;
}
public function checkCredentials($credentials, UserInterface $user)
{
return $this->passwordEncoder->isPasswordValid(
$user,
$credentials['password']
);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function getPassword($credentials): ?string
{
return $credentials['password'];
}
public function onAuthenticationSuccess(
Request $request,
TokenInterface $token,
$providerKey
) {
if (
$targetPath = $this->getTargetPath(
$request->getSession(),
$providerKey
)
) {
return new RedirectResponse($targetPath);
}
return new RedirectResponse($this->urlGenerator->generate('home'));
}
protected function getLoginUrl()
{
return $this->urlGenerator->generate('app_login');
}
}

这是 Security.yml 文件

security:
encoders:
AppEntityUser:
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: AppEntityUser
property: matricule
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
anonymous: lazy
guard:
authenticators:
- AppSecurityAuthAuthenticator
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
role_hierarchy:
ROLE_ADMIN: [ROLE_USER, ROLE_ADMIN, ROLE_SUPER_ADMIN]
ROLE_GESTIONNAIRE: [ROLE_USER, ROLE_ADMIN]
access_control:
- { path: ^/admin, roles: [ROLE_ADMIN, ROLE_GESTIONNAIRE] }
- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/publication, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/publication/new, roles: ROLE_USER }
- { path: ^/comment, roles: ROLE_USER }
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/profile, roles: ROLE_USER }

这是成功重定向页面的一部分

<div id="main">
<div class="inner">
<!-- Header -->
<header id="header">
<a href="{{ path('home') }}" class="logo">
<strong>
{% block pagename %}
{% endblock %}
</strong> COMSAS
</a>
<ul class="icons">
{% if app.user %}
<li><a href="#">{{ app.user.username }}</a></li>
<li>
<a href="/logout">Deconnexion</a>
</li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{% else %}
<li>
<a href="{{ path('app_login') }}" class="icon fas fa-user">
<span class="label">Login</span>
</a>
</li>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
{% endif %}
<li>
<a href="#" class="icon brands fa-twitter">
<span class="label">Twitter</span>
</a>
</li>
<li>
<a href="#" class="icon brands fa-facebook-f">
<span class="label">Facebook</span>
</a>
</li>
<li>
<a href="{{ path('publication_index') }}"
class="icon fas fa-comments">
<span class="label">Forum</span>
</a>
</li>
</ul>
</header>
{% block body %}
{% endblock %}
</div>
</div>
<!-- Sidebar -->
<div id="sidebar">
<div class="inner">
<!-- Search -->
<section id="search" class="alt">
<form method="post" action="#">
<input type="text" name="query" id="query" placeholder="Search" />
</form>
</section>
<!-- Menu -->
<nav id="menu">
<header class="major">
<h2>
Menu
</h2>
</header>
<ul>
{% if is_granted('ROLE_ADMIN') %}
<li><a href="{{ path('admin_home') }}">Espace Admin</a></li>
{% elseif is_granted('ROLE_GESTIONNAIRE') %}
<li><a href="{{ path('admin_home') }}">Gestionnaire</a></li>
{% else %}
<li><a href="{{ path('publication_index') }}">Forum</a></li>
{% endif %}
<li><a href="{{ path('home') }}">Homepage</a></li>
<li><a href="{{ path('generic') }}">Generic</a></li>
<li><a href="{{ path('elements') }}">Elements</a></li>

我需要您的帮助,因为我不明白为什么即使身份验证成功,会话仍然为空。

我相信问题出在您的access_control配置中。

access_control的工作方式是,它将从 ACL 的顶部开始,在与路径匹配的第一行停止。

在您的情况下,发生的情况是路由不匹配 ^/admin,因此它转到第二行并与 ^/匹配,因此将用户视为匿名用户。

我看到解决此问题所需的两个更改:

首先,将基本路径 ACL 移动到最后一个位置,因为它的限制最少,每个 url 都会匹配。

这个

- { path: ^/, roles: IS_AUTHENTICATED_ANONYMOUSLY }

其次,当 ACL 角色IS_AUTHENTICATED_ANONYMOUSLY时,它将在您的用户会话中加载匿名令牌,因此,而不是您的预期用户。

access_control的最终结果将是:

access_control:
- { path: ^/admin, roles: [ROLE_ADMIN, ROLE_GESTIONNAIRE] }    
- { path: ^/publication, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/publication/new, roles: ROLE_USER }
- { path: ^/comment, roles: ROLE_USER }
- { path: ^/login$, roles: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/profile, roles: ROLE_USER }
- { path: ^/, roles: ROLE_USER }

编辑:好的,我刚刚意识到您正在尝试让您的主页"^/"匿名并经过身份验证。

您需要在ACL的底部也有[ROLE_USER,IS_AUTHENTICATED_ANONYMOUSLY]。

现在,使用您所做的最新更改,可能是您在登录后被重定向到登录名。

如果你在FormLoginAuthenticator中查看方法onAuthenticationSuccess((

$targetPath有一个重定向,它优先于主页。

//If $targetPAth == "/login", you're redirected to login, therefore an anonymous token.
if ( $targetPath = $this->getTargetPath($request->getSession(),$providerKey) )
{
return new RedirectResponse($targetPath);
}

可能是$targetPath是 ACL 中IS_AUTHENTICATED_ANONYMOUSLY的"/login"。因此,通过在登录后输入路由"/login",在会话中放置一个匿名令牌。

如果这不起作用,共享您的登录表单 twig 模板以及您的路线及其 URL 将有很大帮助。

最新更新