当前位置: 首页 > 知识库问答 >
问题:

升级到新的symfony authenticator系统:无法再登录[重复]

谭敏学
2023-03-14

从Symfony 4升级到最新的Symfony 5版本后,我尝试升级我的注册和登录表单保护功能,使其成为验证器功能。

在尝试了很多东西,并一次又一次地使用make: usermake: auth命令后,我现在处于一个没有警告,没有错误的情况下,只是当我试图登录时,什么都没有发生:没关系无论用户名/密码组合是否正确,我只是回到登录表单。

以下是我认为可能与该问题相关的文件:

配置/包/security.yaml

security:
    enable_authenticator_manager: true

    password_hashers:
        App\Entity\Player:
            algorithm: auto

    providers:
        app_user_provider:
            entity:
                class: App\Entity\Player
                property: email

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider
            custom_authenticator: App\Security\LoginFormAuthenticator
            logout:
                path: app_logout
            remember_me:
                secret: '%kernel.secret%'
                lifetime: 604800
                path: /
                always_remember_me: true
            switch_user: true

    access_control:
        # - { path: ^/admin, roles: ROLE_ADMIN }
        # - { path: ^/profile, roles: ROLE_USER }

src/Controller/SecurityController.php

<?php

    namespace App\Controller;

    use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
    use Symfony\Component\HttpFoundation\Response;
    use Symfony\Component\Routing\Annotation\Route;
    use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;

    class SecurityController extends AbstractController
    {
        /**
         * @Route("/login", name="app_login")
         */
        public function login(AuthenticationUtils $authenticationUtils): Response
        {
            // If the user is logged in, redirect them to their profile page.
            if ($this->getUser()) {
                return $this->redirectToRoute('player_control_panel');
            }

            // 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]);
        }

        /**
         * @Route("/logout", name="app_logout")
         */
        public function logout()
        {
            throw new \LogicException('This method can be blank - it will be intercepted by the logout key on your firewall.');
        }
    }

src/Entity/Player.php

<?php

namespace App\Entity;

use App\Repository\PlayerRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity(repositoryClass=PlayerRepository::class)
 * @UniqueEntity(fields={"email"}, message="There is already an account with this email")
 */
class Player implements UserInterface, PasswordAuthenticatedUserInterface
{
    /**
     * @ORM\Id
     * @ORM\GeneratedValue
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @ORM\Column(type="string", length=180, unique=true)
     */
    private $email;

    /**
     * @ORM\Column(type="json")
     */
    private $roles = [];

    /**
     * @var string The hashed password
     * @ORM\Column(type="string")
     */
    private $password;

    /**
     * @ORM\Column(type="boolean")
     */
    private $isVerified = false;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getEmail(): ?string
    {
        return $this->email;
    }

    public function setEmail(string $email): self
    {
        $this->email = $email;

        return $this;
    }

    /**
     * A visual identifier that represents this user.
     *
     * @see UserInterface
     */
    public function getUserIdentifier(): string
    {
        return (string) $this->email;
    }

    /**
     * @deprecated since Symfony 5.3, use getUserIdentifier instead
     */
    public function getUsername(): string
    {
        return (string) $this->email;
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        $roles = $this->roles;
        // guarantee every user at least has ROLE_USER
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function setRoles(array $roles): self
    {
        $this->roles = $roles;

        return $this;
    }

    /**
     * @see PasswordAuthenticatedUserInterface
     */
    public function getPassword(): string
    {
        return $this->password;
    }

    public function setPassword(string $password): self
    {
        $this->password = $password;

        return $this;
    }

    /**
     * Returning a salt is only needed, if you are not using a modern
     * hashing algorithm (e.g. bcrypt or sodium) in your security.yaml.
     *
     * @see UserInterface
     */
    public function getSalt(): ?string
    {
        return null;
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials()
    {
        // If you store any temporary, sensitive data on the user, clear it here
        // $this->plainPassword = null;
    }

    public function isVerified(): bool
    {
        return $this->isVerified;
    }

    public function setIsVerified(bool $isVerified): self
    {
        $this->isVerified = $isVerified;

        return $this;
    }
}

src/Security/LoginFormAuthenticator.php

<?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 = 'app_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->request->get('_csrf_token')),
            ]
        );
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        $request->getSession()->getFlashBag()->add('success', "You are now signed in. Greetings, commander.");

        if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
            return new RedirectResponse($targetPath);
        }

        return new RedirectResponse($this->urlGenerator->generate('app_index'));
    }

    protected function getLoginUrl(Request $request): string
    {
        return $this->urlGenerator->generate(self::LOGIN_ROUTE);
    }
}

我只是看不出哪里出了问题,如果你有一个想法,或者即使你能给我一个想法,让我知道哪里出了问题,我会很感激的。非常感谢。

共有1个答案

松旭
2023-03-14

抱歉,这是一个重复的Symfony simple登录表单,新的身份验证方法不起作用,我在发布后几分钟发现了它(我发誓我以前搜索过,但没有找到它)。

问题确实是authenticator类中缺少supports()方法,抽象登录表单authenticator中的方法显然是不够的。添加该方法修复了它:

在src/Security/LoginFormAuthenticator.php

    public function supports(Request $request): bool
    {
        return self::LOGIN_ROUTE === $request->attributes->get('_route')
            && $request->isMethod('POST');
    }

完整文件:

<?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 = 'app_login';

    private UrlGeneratorInterface $urlGenerator;

    public function __construct(UrlGeneratorInterface $urlGenerator)
    {
        $this->urlGenerator = $urlGenerator;
    }

    public function supports(Request $request): bool
    {
        return self::LOGIN_ROUTE === $request->attributes->get('_route')
            && $request->isMethod('POST');
    }

    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->request->get('_csrf_token')),
            ]
        );
    }

    public function onAuthenticationSuccess(Request $request, TokenInterface $token, string $firewallName): ?Response
    {
        $request->getSession()->getFlashBag()->add('success', "You are now signed in. Greetings, commander.");

        if ($targetPath = $this->getTargetPath($request->getSession(), $firewallName)) {
            return new RedirectResponse($targetPath);
        }

        return new RedirectResponse($this->urlGenerator->generate('app_index'));
    }

    protected function getLoginUrl(Request $request): string
    {
        return $this->urlGenerator->generate(self::LOGIN_ROUTE);
    }
}
 类似资料:
  • 1.1.1. 系统升级 1.1.1. 系统升级 根据系统升级介绍,应用层接口只需写入 misc 分区标志位接口。 接口 上层应用程序由 Nodejs 调用,底层提供了 librecovery C库,此库提供了写升级标志的接口,第三方厂商可以根据此进行修改自己的 OTA 升级。 struct boot_cmd { char boot_mode[32]; // 升级

  • 1.1. 系统升级 1.1.1. 系统分区 1.1.2. 升级流程 1.1. 系统升级 RokidOS 为第三方厂商提供了 OTA 相关方案。 1.1.1. 系统分区 由于文件系统的问题,线刷的固件包为aml_upgrade_package.img,而 OTA 所使用的固件包为rokid_upgrade_package.img,二者打包格式不同在于 system 分区的不同。 对于采用 Amlog

  • 1.1. 目录 1.1.1. 系统发布服务 1.1.2. 系统发布流程 1.1.3. 分组管理 1.1. 目录 本文介绍如何通过“Rokid开放平台”对设备进行系统升级。 一、系统发布服务 二、系统发布流程 三、分组管理 1.1.1. 系统发布服务 可通过此服务既可以进行全量升级,也可以进行分组升级,还可以区分测试版本、灰度版本和正式版本。在文件选择时支持两种方式:1)自有服务器填写升级文件路径;

  • 我们没有通过magento连接安装m2epro,因此我们无法升级M2epro。M2epro支持团队建议删除以下文件并使用Magento连接安装。 应用程序/代码/社区/Ess/M2ePro、应用程序/设计/adminhtml/默认/默认/布局/M2ePro.xml、应用程序/设计/adminhtml/默认/默认/模板/M2ePro、应用程序/等/模块/Ess_M2ePro.xml、js/M2ePr

  • 我目前正在使用登录系统将GCM实现到一个应用程序中。我想根据登录到应用程序的用户(一个设备,多个用户)向应用程序发送通知。我经历了这些过程。 以“用户A”身份登录 我不确定如何让应用程序识别登录到设备的用户,并将消息推送给该特定用户。而不是用户B登录并获得用户A的通知。任何意见和答案将高度赞赏!如果您需要检查我的项目的特定代码,请让我知道。

  • 我使用的是Spring Security 4.1.1,但我遇到了一个问题:我试图访问URL,应用程序会重定向到登录页面。到现在为止,一直都还不错。 但是,成功登录后,应用程序会再次将我重定向到登录页面,并且不会创建任何会话,因此即使尝试直接访问URL(在URL栏中键入),应用程序也会重定向到登录页面。 有一些URL我必须要求登录才能访问它们。其他的,我可以访问无需身份验证。这些我不需要验证的URL