Symfony 5.3 - 为什么我的记住我功能不起作用?

问题描述 投票:0回答:3

我刚刚将我的 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

php symfony security yaml symfony5
3个回答
15
投票

我设置了一个测试应用程序并确认“记住我”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(),
            ]
        );

这一切似乎对我有用。


0
投票

我遇到了同样的问题,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;
}

0
投票

我的解决方案是从本地主机删除cookie,它似乎与其他项目的cookie冲突。

© www.soinside.com 2019 - 2024. All rights reserved.