簡體   English   中英

成功登錄 Symfony 4 后用戶仍然匿名

[英]User still Anonymous after successful login Symfony 4

所以我創建了一個傳統的登錄表單。 成功登錄后,它重定向到我的儀表板,然后重定向回登錄。 檢查后,用戶是匿名的,並通過身份驗證。 我還能夠將用戶轉儲到我的自定義提供程序上。 我懷疑,Symfony 不會在會話中保存它。 為什么呢?

這是我到目前為止所做的:

安全.yml:

security:
    encoders:
        App\Entity\User:
            algorithm: bcrypt
    providers:
        user_provider:
            id: App\Security\UserProvider
    firewalls:
        dev:
            pattern: ^/(_(profiler|wdt)|css|images|js)/
            security: false
        main:
            anonymous: ~
            form_login:
                login_path: security_login
                check_path: security_login
                default_target_path: dashboard

            # activate different ways to authenticate

            # http_basic: ~
            # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate

            # form_login: ~
            # https://symfony.com/doc/current/security/form_login_setup.html

    access_control:
        - { path: ^/login, roles: IS_AUTHENTICATED_ANONYMOUSLY }
        - { path: ^/, roles: ROLE_ADMIN }

    role_hierarchy:
        ROLE_SUPER_ADMIN:
            - ROLE_ALLOWED_TO_SWITCH
            - ROLE_ADMIN

框架.yml

framework:
    secret: '%env(APP_SECRET)%'
    #default_locale: en
    #csrf_protection: ~
    #http_method_override: true

    # Enables session support. Note that the session will ONLY be started if you read or write from it.
    # Remove or comment this section to explicitly disable session support.
    session:
        # https://symfony.com/doc/current/reference/configuration/framework.html#handler-id
        handler_id: session.handler.native_file
        save_path: '%kernel.project_dir%/var/sessions/%kernel.environment%'

    #esi: ~
    #fragments: ~
    php_errors:
        log: true

    cache:
        # Put the unique name of your app here: the prefix seed
        # is used to compute stable namespaces for cache keys.
        #prefix_seed: your_vendor_name/app_name

        # The app cache caches to the filesystem by default.
        # Other options include:

        # Redis
        #app: cache.adapter.redis
        #default_redis_provider: redis://localhost

        # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
        #app: cache.adapter.apcu

用戶提供者

class UserProvider implements UserProviderInterface
{
    private $em;

    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
    }

    public function loadUserByUsername($username)
    {   
        $user = $this->em->getRepository(User::class)->loadByUsername($username);

        if ($user) {
            return $user;
        }

        throw new UsernameNotFoundException(
            sprintf('Username "%s" does not exist.', $username)
        );
    }

    public function refreshUser(UserInterface $user)
    {
        if (!$user instanceof User) {
            throw new UnsupportedUserException(
                sprintf('Instances of "%s" are not supported.', get_class($user))
            );
        }

        return $this->loadUserByUsername($user->getUsername());
    }

    public function supportsClass($class)
    {
        return User::class === $class;
    }
}

用戶

use Symfony\Component\Security\Core\User\UserInterface;

/**
 * @ORM\Entity()
 * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
 * @UniqueEntity("email", message="Email is already taken.")
 * @UniqueEntity("username", message="Username is already taken.")
 */
class User implements AdvancedUserInterface, EquatableInterface, \Serializable
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank(message="Username must not be blank.")
     */
    private $username;

    /**
     * @Assert\NotBlank(message="Password must not be blank.")
     */
    private $plainPassword;

    /**
     * @ORM\Column(type="string", length=255)
     */
    private $password;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank(message="Email must not be blank.")
     * @Assert\Email()
     */
    private $email;

   /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank(message="First name must not be blank.")
     */
    private $firstName;

    /**
     * @ORM\Column(type="string", length=255)
     * @Assert\NotBlank(message="Last name must not be blank.")
     */
    private $lastName;

    /**
     * @ORM\Column(type="json_array")
     */
    private $roles;

    public function __construct()
    {
        $this->roles = [];
    }

    public function setFirstName(string $firstName)
    {
        $this->firstName = $firstName;

        return $this;
    }

    public function getFirstName(): ?string
    {
        return $this->firstName;
    }

    public function setLastName(string $lastName)
    {
        $this->lastName = $lastName;

        return $this;
    }

    public function getLastName(): ?string
    {
        return $this->lastName;
    }

    public function setUsername(string $username): User
    {
        $this->username = $username;

        return $this;
    }

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

        return $this;
    }

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

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

        return $this->password;
    }

    public function setPlainPassword($plainPassword) : User
    {
        $this->plainPassword = $plainPassword;

        return $this;
    }

    public function getPlainPassword() : ?string
    {
        return $this->plainPassword;
    }

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

        return $this;
    }

    // Overriden Methods

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

    public function getUsername()
    {
        return $this->username;
    }

    public function eraseCredentials()
    {

    }

    public function isEqualTo(UserInterface $user)
    {
        if (!$user instanceof WebserviceUser) {
            return false;
        }

        if ($this->password !== $user->getPassword()) {
            return false;
        }

        if ($this->salt !== $user->getSalt()) {
            return false;
        }

        if ($this->username !== $user->getUsername()) {
            return false;
        }

        return true;
    }

    public function isAccountNonExpired()
    {
        return true;
    }

    public function isAccountNonLocked()
    {
        return true;
    }

    public function isCredentialsNonExpired()
    {
        return true;
    }

    public function isEnabled()
    {
        return true;
    }

    public function serialize()
    {
        return serialize(array(
            $this->id,
            $this->username,
            $this->password,
            $this->roles,
        ));
    }

    public function unserialize($serialized)
    {
        list (
            $this->id,
            $this->username,
            $this->password,
            $this->roles
        ) = unserialize($serialized);
    }

    public function getRoles()
    {
        $roles = $this->roles;
        $roles[] = 'ROLE_USER';

        return array_unique($roles);
    }

    public function getSalt()
    {
        return null;
    }
}

謝謝!

注意:我將 docker 與 Nginx 和 PHP-FPM 圖像一起使用。

今天我自己也遇到了同樣的問題,並且臉部也有了類似的時刻。 就我而言,事實證明我們並未序列化要在AdvancedUserInterface方法中使用的所有必需的User實體數據。

例如:

UserEntity

...

public function isEnabled ()
{
    return (0 < $this->status);
}

public function serialize ()
{
    return serialize(array(
        $this->id,
        $this->username,
        $this->password,
        // $this->status, <- this was missing and needed added
    ));
}

public function unserialize ($serialized)
{
    list (
        $this->id,
        $this->username,
        $this->password
        //, $this->status <-- this was missing and needed added

    ) = unserialize($serialized, array ("allowed_classes" => false));
}

...

因為我們沒有使用$this->status屬性來序列化該對象,所以使用未序列化的UserEntity時, isEnabled()方法失敗。 添加屬性並清除會話后,它又可以正常工作了。

這可能會對某人有所幫助,我在此上花了幾個小時,並且遇到了類似的問題..確保用戶序列化正確

造成很多痛苦的原因..

public function serialize()
{
    return serialize(array(
        $this->id, $this->username, $this->password, // see section on salt below
        // $this->salt,
    ));
}

public function unserialize($serialized)
{
    list ($this->id, $this->username, $this->password, // see section on salt below
        // $this->salt
        ) = unserialize($serialized, array('allowed_classes' => false));
}

固定

public function serialize()
{
    return serialize(array(
        $this->id, $this->username, $this->password, $this->salt,
    ));
}

public function unserialize($serialized)
{
    list ($this->id, $this->username, $this->password, $this->salt) 

        = unserialize($serialized, array('allowed_classes' => false));
}

用戶創建...

        $user->setSalt(bin2hex(random_bytes(16)));

        $encoder = new MessageDigestPasswordEncoder('sha512', true, 5000);

        $encodedPassword = $encoder->encodePassword($password, $user->getSalt());

        $user->setPassword($encodedPassword);

在從 Symfony2 到 Symfony 5 的項目遷移過程中遇到了這個問題。所以,我做了什么:

將用戶實體文件重命名為 User.php_

按照文檔中的描述運行 php bin/console make:user

然后將來自生成實體的方法與現有實體進行比較。

另外,從 User 實體中刪除了 \\Serializable 接口,因為我不需要它(如果您需要一個實體可序列化,只需正確實現它)

如果你從舊版本的 Symfony 遷移到 4/5 版本,最好用所有相關的東西(比如配置、登錄和注冊控制器)重新生成表單登錄並重新實現它: https : //symfony.com /doc/current/security/form_login_setup.html

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM