问题描述
我已将symfony 4配置为在用户选中复选框时设置“记住我” cookie。这可以正常工作。但是,当我重新启动浏览器并返回网站时,该网站删除了cookie。 symfony日志如下所示:
[Application] Oct 21 14:14:12 |DEBUG | SECURI Remember-me cookie detected.
[Application] Oct 21 14:14:12 |INFO | SECURI User for remember-me cookie not found.
[Application] Oct 21 14:14:12 |DEBUG | DOCTRI SELECT t0.id AS id_1,t0.email AS email_2,t0.roles AS roles_3,t0.password AS password_4,t0.is_verified AS is_verified_5,t0.pending_surfpoints AS pending_surfpoints_6,t0.surfpoints_total AS surfpoints_total_7,t0.balance AS balance_8,t0.username AS username_9,t0.ref_earning AS ref_earning_10,t0.ref_id AS ref_id_11 FROM user t0 WHERE t0.email = ? LIMIT 1 0="myUsername"
[Application] Oct 21 14:14:12 |DEBUG | SECURI Clearing remember-me cookie. name="REMEMBERME"
我将用户登录名配置为使用电子邮件和用户名(下面提到了我的更改)。我认为现在的问题是,“记住我” cookie在数据库的用户名部分中搜索用户名。
我更改了UserAuthentificatorAuthenticator.PHP中的getUser函数以查找电子邮件,如果用户名失败,则该电子邮件:
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) {
//Email Could not be found - try username
$user = $this->entityManager->getRepository(User::class)->findOneBy(['username' => $credentials['email']]);
if (!$user){
// fail authentication with a custom error
throw new CustomUserMessageAuthenticationException('Email/Username konnten nicht gefunden werden.');
}
}
if (!$user->isverified()){
throw new CustomUserMessageAuthenticationException('Der Account wurde noch nicht aktiviert.');
}
return $user;
}
我现在可以在哪里修改Cookie身份验证器以使其正常工作?
编辑: 我的security.yaml
security:
encoders:
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:
anonymous: true
lazy: true
provider: app_user_provider
guard:
authenticators:
- App\Security\UserAuthentificatorAuthenticator
logout:
path: app_logout
# where to redirect after logout
target: app_default_start
remember_me:
secret: '%kernel.secret%'
lifetime: 604800 # 1 week in seconds
path: /
解决方法
您正在使用的内置EntityUserProvider
根据配置中指定的属性查找User
对象。 “记住我”功能使用Provider
查找用户,并且由于您的用户可以使用email
或username
登录,因此仅通过email
查找时,找不到默认用户。您应该将查找逻辑移出Authenticator
并移至UserProvider
。
在您的UserRepository
中添加以下功能,并将其设置为implement UserLoaderInterface
:
public function loadUserByUsername($identifier)
{
$qb = $this->createQueryBuilder('u');
return $qb->where('u.username = :identifier')
->orWhere('u.email = :identifier')
->setParameter('identifier',$identifier)
->getQuery()
->getOneOrNullResult();
}
在security.yaml
中,删除property
:
app_user_provider:
entity:
class: App\Entity\User
更改身份验证者:
$token = new CsrfToken('authenticate',$credentials['csrf_token']);
if (!$this->csrfTokenManager->isTokenValid($token)) {
throw new InvalidCsrfTokenException();
}
$user = $userProvider->loadUserByUsername($credentials['email']);
if (!$user) {
throw new CustomUserMessageAuthenticationException('Email/Username konnten nicht gefunden werden.');
}
if (!$user->isVerified()){
throw new CustomUserMessageAuthenticationException('Der Account wurde noch nicht aktiviert.');
}
return $user;