#php #symfony #session #doctrine-orm #logged
#php #symfony #сеанс #doctrine-orm
Вопрос:
Я использую Symfony 2.8 и Doctrine, и у меня есть security.yml, настроенный так, чтобы указывать на класс User, который реализует UserInterface. Моя схема ORM находится в YAML.
Проблема:
- В базе данных пользователь также указал поле «email», Symfony для ЗАРЕГИСТРИРОВАННОГО ПОЛЬЗОВАТЕЛЯ не заполняет это поле, а также поле «пароль» пустое.
Когда я это делаю $this->get('doctrine.orm.entity_manager')->clear(User::class);
, диспетчер объектов правильно выбирает объект. Но когда объект ВЫХОДИТ ИЗ СЕАНСА, это неверно.
Проблема также в том, что когда я пытаюсь извлечь новый объект из базы данных с помощью find() в репозитории, тогда извлекается неправильный элемент из сеанса, когда я не буду использовать $em->clear(User::class)
Как сообщить Symfony / Doctrine создать мою сущность таким образом, чтобы все поля были заполнены, поэтому она станет постоянной?
<?php
namespace XXXAppBundleModelEntity;
use XXXAppBundleModelEntityServerLogging;
use DoctrineORMMapping as ORM;
use SymfonyComponentSecurityCoreUserUserInterface;
/**
* User
*/
class User implements UserInterface
{
/**
* @var integer $id
*/
protected $id;
/**
* @var string $username
*/
protected $username;
/**
* @var string $email
*/
protected $email;
/**
* @var string $password
*/
protected $password;
/**
* @var array $roles
*/
protected $roles = array();
/**
* @var DoctrineCommonCollectionsCollection $logEvents
*/
protected $logEvents;
/**
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getUsername()
{
return $this->username;
}
/**
* @param string $username
* @return $this
*/
public function setUsername($username)
{
$this->username = $username;
return $this;
}
/**
* @return string
*/
public function getEmail()
{
return $this->email;
}
/**
* @param string $email
* @return $this
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* {@inheritdoc}
*/
public function getPassword()
{
return $this->password;
}
/**
* @param string $password
* @return $this
*/
public function setPassword($password)
{
$this->password = $password;
return $this;
}
/**
* Returns the roles or permissions granted to the user for security.
*/
public function getRoles()
{
$roles = $this->roles;
// guarantees that a user always has at least one role for security
if (empty($roles)) {
$roles[] = 'ROLE_USER';
}
return array_unique($roles);
}
public function setRoles(array $roles)
{
$this->roles = $roles;
}
/**
* Returns the salt that was originally used to encode the password.
*/
public function getSalt()
{
// See "Do you need to use a Salt?" at http://symfony.com/doc/current/cookbook/security/entity_provider.html
// we're using bcrypt in security.yml to encode the password, so
// the salt value is built-in and you don't have to generate one
return;
}
/**
* Removes sensitive data from the user.
*/
public function eraseCredentials()
{
$this->password = null;
$this->email = null;
}
/**
* Appends an entry to administration log
*
* @param XXXAppBundleModelEntityServerLogging $logEvent
* @return $this
*/
public function appendLog(ServerLogging $logEvent)
{
if (!$this->logEvents->contains($logEvent))
{
$this->logEvents->add($logEvent);
}
return $this;
}
/**
* Remove a log entry from the history
*
* @param XXXAppBundleModelEntityServerLogging $logEvent
* @return $this
*/
public function clearLogEntry(ServerLogging $logEvent)
{
$this->logEvents->removeElement($logEvent);
return $this;
}
}
И конфигурация ORM:
XXXAppBundleModelEntityUser:
type: entity
table: users
repositoryClass: XXXAppBundleModelRepositoryUserRepository
id:
id:
type: integer
scale: 0
length: null
unique: false
nullable: false
precision: 0
id: true
generator:
strategy: IDENTITY
fields:
username:
type: string
scale: 0
length: null
unique: true
nullable: false
precision: 0
email:
type: string
scale: 0
length: null
unique: true
nullable: false
precision: 0
password:
type: string
scale: 0
length: null
unique: false
nullable: false
precision: 0
roles:
type: json_array
scale: 0
length: null
unique: false
nullable: false
precision: 0
oneToMany:
logEvents:
targetEntity: XXXAppBundleModelEntityServerLogging
cascade:
- remove
- persist
fetch: LAZY
mappedBy: author
inversedBy: null
orphanRemoval: false
orderBy: null
lifecycleCallbacks: { }
Комментарии:
1. Как вы извлекаете своего пользователя из сеанса, каков код в вашем классе User?
2. Да, я извлекаю пользователя из сеанса. В классе user я только что защитил частные свойства геттеры. И файл ORM yml выглядит нормально, как и в других объектах.
3. Пожалуйста, отправьте код.
4.pastebin.com/CNQf8dCd pastebin.com/VkyRDHXx Спасибо вам!
Ответ №1:
Вы реализовали метод UserInterface::eraseCredentials() таким образом, что он отключает адрес электронной почты и пароль:
public function eraseCredentials()
{
$this->password = null;
$this->email = null;
}
Symfony вызовет этот метод перед сериализацией объекта, чтобы сохранить его в сеансе.
UserInterface::eraseCredentials() предназначен для удаления конфиденциальных данных из объекта user, чтобы они не попали, например, в файлы сеанса, но нет реальной необходимости удалять электронное письмо, как вы делаете. Лучшим примером может быть, если вы храните текстовую версию пароля пользователя где-нибудь на этом объекте, это то, что вы никогда не хотели бы видеть в файлах сеанса.
Комментарии:
1. Спасибо. Я не удаляю имя пользователя, а просто пароль и адрес электронной почты 🙂
2. Как реализовать смену пароля или изменение списка ролей при удалении электронной почты или пароля?
3. Правильно, но именно поэтому электронное письмо отсутствует при извлечении из сеанса.
4. Не уверен, что вы имеете в виду под этим вопросом @KrzysztofaKrzysztof
5. Хорошо, в любом случае спасибо. Вероятно, мне придется отключить зарегистрированного пользователя в форме редактирования пароля и работать с новым объектом из базы данных.