[英]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.