我刚刚将我的 symfony 4.4 应用程序升级到 5.3 以使用一些新的很酷的东西(UX,UUID,..)。因此,我开始了一个新项目并运行
make:auth
命令以最新默认值创建安全组件。除了“记住我”功能外,一切都很完美。只是未设置 cookie(无论使用哪个浏览器)。也许你可以帮助我
安全.yaml
security:
enable_authenticator_manager: true
password_hashers:
App\Entity\User:
algorithm: auto
providers:
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
pattern: ^/
logout:
path: _logout
target: _index
remember_me:
secret: '%env(APP_SECRET)%'
lifetime: 31536000 # 1 year in seconds
always_remember_me: true
path: _index
switch_user: true
role_hierarchy:
ROLE_USER: ROLE_USER
ROLE_ADMIN: [ROLE_USER, ROLE_ALLOWED_TO_SWITCH]
access_control:
- { path: ^/login, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/reset-password, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/datenschutz, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/impressum, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/worker, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
- { path: ^/, role: ROLE_USER }
登录表单验证器
<?php
namespace App\Security;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Http\Authenticator\AbstractLoginFormAuthenticator;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\CsrfTokenBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Badge\UserBadge;
use Symfony\Component\Security\Http\Authenticator\Passport\Credentials\PasswordCredentials;
use Symfony\Component\Security\Http\Authenticator\Passport\Passport;
use Symfony\Component\Security\Http\Authenticator\Passport\PassportInterface;
use Symfony\Component\Security\Http\Util\TargetPathTrait;
class LoginFormAuthenticator extends AbstractLoginFormAuthenticator
{
use TargetPathTrait;
public const LOGIN_ROUTE = '_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);
}
return new RedirectResponse($this->urlGenerator->generate('_index'));
}
protected function getLoginUrl(Request $request): string
{
return $this->urlGenerator->generate(self::LOGIN_ROUTE);
}
public function supportsRememberMe(): bool
{
return true;
}
}
登录.html.twig
{% extends 'base.html.twig' %}
{% block title %}{{ ('meta.title.login')|trans }}{% endblock %}
{% block body %}
<h1>{{ ('security.login.header')|trans }}</h1>
<form method="post">
{% if error %}
<div class="alert alert-danger">{{ error.messageKey|trans(error.messageData, 'security') }}</div>
{% endif %}
<div class="mb-3">
<label for="inputEmail" class="form-label">{{ ('security.login.email')|trans }}</label>
<input type="email" value="{{ last_username }}" name="email" id="inputEmail" class="form-control" autocomplete="email" required autofocus>
</div>
<div class="mb-3">
<label for="inputPassword" class="form-label">{{ ('security.login.password')|trans }}</label>
<input type="password" name="password" id="inputPassword" class="form-control" autocomplete="current-password" required>
</div>
<div class="mb-3">
<a href="{{ path('app_forgot_password_request') }}">
{{ ('button.forgot_password')|trans }}
</a>
</div>
<input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
<button class="btn btn-lg btn-outline-success" type="submit">
{{ ('security.login.button')|trans }}
</button>
</form>
{% endblock %}
提前非常感谢!
-------------- 编辑 ----------------------
我最初问这个问题是针对 5.4 版本的,但也与 5.3 相关 - 我都尝试了,但没有设置 cookie
我设置了一个测试应用程序并确认“记住我”cookie 没有被发送,但后来我作弊并在 Symfony Slack 频道上看到了提示。使用基于护照的新身份验证系统时,您需要使用“记住我”徽章。它记录在此处。
因此请使用以下方法更新您的 Authenticator::authenticate 方法:
return new Passport(
new UserBadge($email),
new PasswordCredentials($request->request->get('password', '')),
[
new CsrfTokenBadge('authenticate', $request->get('_csrf_token')),
new RememberMeBadge(),
]
);
这一切似乎对我有用。
我遇到了同样的问题,cookie REMEMBERME 已设置,但在删除 PHPSESSID 时未调用。花了一些时间后,我在我的 User 实体类中发现了这个(我在升级 Symfony 后没有考虑它就添加了):
public function getUserIdentifier() {
return $this->id;
}
但是在 secutiy.yml 中,我的用户提供者是:
app_user_provider:
entity:
class: App\Entity\User
property: email
所以我将 getUserIdentifier 函数更改为这个,现在它可以工作了:
public function getUserIdentifier() {
return $this->email;
}
我的解决方案是从本地主机删除cookie,它似乎与其他项目的cookie冲突。