Problème Symfony 6.1 avec l'impossibilité de se connecter au nouveau site Web à l'aide de la base de données utilisateur du site Web 3.4
P粉129168206
P粉129168206 2024-01-08 17:40:58
0
1
660

J'ai un nouveau site 6.1 créé à partir de zéro et j'essaie de mettre en œuvre la sécurité. J'ai une base de données d'utilisateurs d'un site précédent dans Symfony 3.4 que j'essaie d'utiliser et qui contient des hachages et des sels de mot de passe existants - je souhaite continuer à utiliser les mêmes hachages, donc en utilisant l'algorithme sha1 (j'y réfléchirai plus tard) Mettre à niveau le hachage algorithme). Essayer de se connecter renvoie toujours ce qui suit : 

#message: "The presented password is invalid."
  #code: 0
  #file: "/** redacted **/vendor/symfony/security-http/EventLis tener/CheckCredentialsLis tener.php"
  #line: 69
  #serialized: null
  -token: null
  trace: {▼
    /** redacted **/vendor/symfony/security-http/EventLis tener/CheckCredentialsLis tener.php:69 {▶}
    /** redacted **/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:175 {▶}
    /** redacted **/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php:326 {▶}
    /** redacted **/vendor/symfony/http-foundation/Session/Session.php:258 {▶}
    /** redacted **/vendor/symfony/http-foundation/Session/Session.php:278 {▶}
    /** redacted **/vendor/symfony/http-foundation/Session/Session.php:70 {▶}
    /** redacted **/vendor/symfony/security-http/Authentication/AuthenticationUtils.php:40 {▶}
    /** redacted **/src/Controller/SecurityController.php:33 {▶}
    /** redacted **/vendor/symfony/http-kernel/HttpKernel.php:153 {▶}
    /** redacted **/vendor/symfony/http-kernel/HttpKernel.php:75 {▶}
    /** redacted **/vendor/symfony/http-kernel/Kernel.php:202 {▶}
    /** redacted **/vendor/symfony/runtime/Runner/Symfony/HttpKernelRunner.php:35 {▶}
    /** redacted **/vendor/autoload_runtime.php:29 {▶}
    /** redacted **/public/index.php:5 {▶}
  }
}

Cela a l'air simple, il ne reconnaît pas le mot de passe. Cependant, le mot de passe est le même que celui de la base de données utilisée par le site de la version Symfony 3.4 et utilise exactement le même hacheur de mot de passe.

Il s'agit essentiellement d'un site prêt à l'emploi, je n'ai fait aucune configuration autre que d'essayer de faire fonctionner la sécurité, j'ai suivi exactement la documentation.

Voici mon security.yaml :

# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
    password_hashers:
        AppEntityUsers:
            algorithm:   sha1
            iterations: 1
            encode_as_base64: false

    # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
    providers:
        app_user_provider:
            entity:
                class: AppEntityUsers
                property: email

    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            lazy: true
            provider: app_user_provider
            form_login:
                login_path: login
                check_path: login
                enable_csrf: false
            login_throttling:
                max_attempts: 3 # per minute
                interval: '15 minutes'

Voici SecurityController.php (contient le routage/la connexion) :

namespace AppController;

use AppEntityOffice;
use DoctrinePersistenceManagerRegistry;
use SymfonyBundleFrameworkBundleControllerAbstractController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentHttpFoundationSessionSession;
use SymfonyComponentHttpFoundationSessionStorageHandlerNativeFileSessionHandler;
use SymfonyComponentHttpFoundationSessionStorageNativeSessionStorage;
use SymfonyComponentRoutingAnnotationRoute;
use SymfonyComponentSecurityCoreSecurity;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;
use PsrLogLoggerInterface;

class SecurityController extends AbstractController
{
    public function __construct(private ManagerRegistry $doctrine, private LoggerInterface $logger) {}

    #[Route('/login', name: 'login')]
    public function login(Request $request, AuthenticationUtils $authenticationUtils): Response
    {
        $sessionStorage = new NativeSessionStorage([], new NativeFileSessionHandler());
        $session = new Session($sessionStorage);

        $doctrine    =  $this->doctrine;
        $logger  =  $this->logger;
        $logger->info('loginAction');

        // 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',
            [
                'controller_name' => 'SecurityController',
                // last username entered by the user
                'last_username' => $lastUsername,
                'error'         => $error,
            ]
        );
    }
}

Voici mon login.html.twig :

{% block PageHeader %}{% endblock %}

{% block PageContent %}
    <div style="min-height: 250px;">
        <h1>{{ 'security.login.title'|trans({}) }}</h1>
        <br />

        {% if error %}
            {{ dump(error) }}
            {% if error.messageKey is defined %}
                <div class="error">{{ error.messageKey|trans(error.messageData) }}</div>
            {% endif %}
        {% endif %}

        <form action="{{ path('login') }}" method="post" class="login">
            <label for="username">{{ 'security.login.username'|trans({}) }}</label>
            <input type="text" id="username" name="_username" value="{{ last_username }}" required="required" />

            <br /><br />
            <label for="password">{{ 'security.login.password'|trans({}) }}</label>
            <input type="password" id="password" name="_password" required="required" />
            
            <br />
            <input type="hidden" name="_csrf_token" value="{{ csrf_token('authenticate') }}">
            <input type="submit" id="_submit" name="_submit" value="{{ 'security.login.submit'|trans({}) }}" />
        </form>
    </div>
{% endblock %}

{% block PageFooter %}{% endblock %}

Voici ma classe d'utilisateurs :

namespace AppEntity;

use DoctrineCommonCollectionsArrayCollection;
use DoctrineCommonCollectionsCollection;
use DoctrineDBALTypesTypes;
use DoctrineORMMapping as ORM;

use AppRepositoryUsersRepository;
use SymfonyComponentSecurityCoreUserPasswordAuthenticatedUserInterface;
use SymfonyComponentSecurityCoreUserUserInterface;

/**
 * Users
 *
 * @ORMTable(name="Users", indexes={@ORMIndex(name="IDX_D5428AED73FD6E34", columns={"Office"})})
 * @ORMEntity(repositoryClass="AppRepositoryUsersRepository")
 */
class Users implements UserInterface, PasswordAuthenticatedUserInterface
{
    /**
     * @var int
     *
     * @ORMColumn(name="UserId", type="integer", nullable=false)
     * @ORMId
     * @ORMGeneratedValue(strategy="IDENTITY")
     */
    private $userid;

    /**
     * @var string|null
     *
     * @ORMColumn(name="Firstname", type="string", length=100, nullable=true)
     */
    private $firstname;

    /**
     * @var string|null
     *
     * @ORMColumn(name="Surname", type="string", length=100, nullable=true)
     */
    private $surname;

    /**
     * @var string
     *
     * @ORMColumn(name="Email", type="string", length=150, nullable=false)
     */
    private $email;

    /**
     * @var string|null
     *
     * @ORMColumn(name="JobTitle", type="string", length=150, nullable=true)
     */
    private $jobtitle;

    /**
     * @var string|null
     *
     * @ORMColumn(name="Password", type="string", length=150, nullable=true)
     */
    private $password;

    /**
     * @var string|null
     *
     * @ORMColumn(name="Salt", type="string", length=50, nullable=true)
     */
    private $salt;

    /**
     * @var int|null
     *
     * @ORMColumn(name="Status", type="integer", nullable=true)
     */
    private $status;

    /**
     * @var DateTime|null
     *
     * @ORMColumn(name="CreatedOn", type="datetime", nullable=true)
     */
    private $createdon;

    /**
     * @var int|null
     *
     * @ORMColumn(name="CreatedBy", type="integer", nullable=true)
     */
    private $createdby;

    /**
     * @var DateTime|null
     *
     * @ORMColumn(name="LastUpdatedOn", type="datetime", nullable=true)
     */
    private $lastupdatedon;

    /**
     * @var int|null
     *
     * @ORMColumn(name="LastUpdatedBy", type="integer", nullable=true)
     */
    private $lastupdatedby;

    /**
     * @var DateTime|null
     *
     * @ORMColumn(name="Deleted", type="datetime", nullable=true)
     */
    private $deleted;

    /**
     * @var Office
     *
     * @ORMManyToOne(targetEntity="Office")
     * @ORMJoinColumns({
     *   @ORMJoinColumn(name="Office", referencedColumnName="OfficeId")
     * })
     */
    private $office;

    /**
     * @var DoctrineCommonCollectionsCollection
     *
     * @ORMManyToMany(targetEntity="Usergroup", inversedBy="userid")
     * @ORMJoinTable(name="usergroupmap",
     *   joinColumns={
     *     @ORMJoinColumn(name="UserId", referencedColumnName="UserId")
     *   },
     *   inverseJoinColumns={
     *     @ORMJoinColumn(name="UserGroup", referencedColumnName="UserGroupId")
     *   }
     * )
     */
    private $usergroup = array();

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->usergroup = new DoctrineCommonCollectionsArrayCollection();
    }

    public function getUserid(): ?int
    {
        return $this->userid;
    }

    public function getFirstname(): ?string
    {
        return $this->firstname;
    }

    public function setFirstname(?string $firstname): self
    {
        $this->firstname = $firstname;

        return $this;
    }

    public function getSurname(): ?string
    {
        return $this->surname;
    }

    public function setSurname(?string $surname): self
    {
        $this->surname = $surname;

        return $this;
    }

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

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

        return $this;
    }

    public function getJobtitle(): ?string
    {
        return $this->jobtitle;
    }

    public function setJobtitle(?string $jobtitle): self
    {
        $this->jobtitle = $jobtitle;

        return $this;
    }

    public function getPassword(): ?string
    {
        return $this->password;
    }

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

        return $this;
    }

    public function getSalt(): ?string
    {
        return $this->salt;
    }

    public function setSalt(?string $salt): self
    {
        $this->salt = $salt;

        return $this;
    }

    public function getStatus(): ?int
    {
        return $this->status;
    }

    public function setStatus(?int $status): self
    {
        $this->status = $status;

        return $this;
    }

    public function getCreatedon(): ?DateTimeInterface
    {
        return $this->createdon;
    }

    public function setCreatedon(?DateTimeInterface $createdon): self
    {
        $this->createdon = $createdon;

        return $this;
    }

    public function getCreatedby(): ?int
    {
        return $this->createdby;
    }

    public function setCreatedby(?int $createdby): self
    {
        $this->createdby = $createdby;

        return $this;
    }

    public function getLastupdatedon(): ?DateTimeInterface
    {
        return $this->lastupdatedon;
    }

    public function setLastupdatedon(?DateTimeInterface $lastupdatedon): self
    {
        $this->lastupdatedon = $lastupdatedon;

        return $this;
    }

    public function getLastupdatedby(): ?int
    {
        return $this->lastupdatedby;
    }

    public function setLastupdatedby(?int $lastupdatedby): self
    {
        $this->lastupdatedby = $lastupdatedby;

        return $this;
    }

    public function getDeleted(): ?DateTimeInterface
    {
        return $this->deleted;
    }

    public function setDeleted(?DateTimeInterface $deleted): self
    {
        $this->deleted = $deleted;

        return $this;
    }

    public function getOffice(): ?Office
    {
        return $this->office;
    }

    public function setOffice(?Office $office): self
    {
        $this->office = $office;

        return $this;
    }

    /**
     * @return Collection<int, Usergroup>
     */
    public function getUsergroup(): Collection
    {
        return $this->usergroup;
    }

    public function addUsergroup(Usergroup $usergroup): self
    {
        if (!$this->usergroup->contains($usergroup)) {
            $this->usergroup->add($usergroup);
        }

        return $this;
    }

    public function removeUsergroup(Usergroup $usergroup): self
    {
        $this->usergroup->removeElement($usergroup);

        return $this;
    }

    /**
     * @see UserInterface
     */
    public function eraseCredentials(): array
    {
        // If you store any temporary, sensitive data on the user, clear it here
    }

    /**
     * @see UserInterface
     */
    public function getRoles(): array
    {
        foreach ($this->usergroup as $key => $value)
        {
            $roles[] = $value->getUsergroup();
        }
        return array_unique($roles);
    }

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

Est-ce que quelqu'un sait comment résoudre ce problème ?

P粉129168206
P粉129168206

répondre à tous(1)
P粉523335026

Résolu ! La première chose est de faire hériter de ma classe User LegacyPasswordAuthenticatedUserInterface 而不是 PasswordAuthenticatedUserInterface.

La deuxième chose est de vérifier /vendor/symfony/password-hasher/Hasher/MessageDigestPasswordHasher.php,并在 verify 函数中,注释掉开头的块行 if (strlen($hashedPassword) !== $this->hashLength || str_contains($hashedPassword, '$')) {.

Ce bloc renvoie false en permanence car $this->hashLength 始终为 -1。 $this->hashLength est défini dans le constructeur, je ne sais pas pourquoi il renvoie toujours -1 ou si cette vérification est valide, mais le commenter m'a permis de me connecter :)

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal