PDO exception at login submission
- paolo
- Member | 15
I have aproblem with login.
When I submit the login form I get a PDO exception:
You cannot serialize or unserialize PDO instances.
If I don't delete the session cookie not only my application, but all Nette examples fail to work and show an error page with the same exception (generated by session_start() call).
These are the last calls (as showed by the debug page, but in reverse order):
UserAccessPresenter.php:
public function loginFormSubmitted($form)
{
try
{
$values = $form->getValues();
if ($values->remember)
$this->user->setExpiration('+ 14 days', FALSE);
else
$this->user->setExpiration('+ 20 minutes', TRUE);
>>>>>>> $this->user->login($values->username, $values->password);
$this->flashMessage('Hello, '.$values->username.'. You are now logged in');
$this->restoreRequest($this->backlink);
$this->redirect('Homepage:default');
}
Nette/Security/User.php:
public function login($id = NULL, $password = NULL)
{
$this->logout(TRUE);
if (!$id instanceof IIdentity) {
$credentials = func_get_args();
$id = $this->getAuthenticator()->authenticate($credentials);
}
$this->storage->setIdentity($id);
>>>>>> $this->storage->setAuthenticated(TRUE);
$this->onLoggedIn($this);
}
Nette/Http/UserStorage.php
public function setAuthenticated($state)
{
$section = $this->getSessionSection(TRUE);
$section->authenticated = (bool) $state;
// Session Fixation defence
>>>>>> $this->sessionHandler->regenerateId();
if ($state) {
$section->reason = NULL;
$section->authTime = time(); // informative value
Nette/Http/Session.php:
public function regenerateId()
{
if (self::$started && !$this->regenerated) {
if (headers_sent($file, $line)) {
throw new Nette\InvalidStateException("Cannot regenerate session ID after HTTP headers have been sent" . ($file ? " (output started at $file:$line)." : "."));
}
session_regenerate_id(TRUE);
>>>>>>> session_write_close();
$backup = $_SESSION;
session_start();
$_SESSION = $backup;
}
$this->regenerated = TRUE;
}
inner-code PDO→ __sleep ()
- paolo
- Member | 15
Solved!
In the Authenticator class, I passed to the Identity constructor an instance of
GroupedSelection (returned by the related() method of class ActiveRow) instead
of an array.
Being not particularly expert of PHP, I thought that, because GroupedSelection
implements the interface ArrayAccess, could also be converted in array by cast
(used in Identity constructor). In fact it was converted, but not the way
I expected. The conversion was performed as for any other class, including all
class members, among which there must be some references to PDO objects.
Being such Identity included in the session store, it is subject to
serialization/unserialization, and this is the reason of the exception.
I hope this could help someone else with similar problems.
public function authenticate(array $credentials)
{
list($username, $password) = $credentials;
$row = $this->database->table('user')->where('username', $username)->fetch();
if (!$row) {
throw new NS\AuthenticationException("User '$username' not found.", self::IDENTITY_NOT_FOUND);
}
if ($row->password !== $this->calculateHash($password)) {
throw new NS\AuthenticationException("Invalid password.", self::INVALID_CREDENTIAL);
}
unset($row->password);
>>>> $roles = $row->related('user_role', 'user_id');
return new NS\Identity($row->id, $roles, $row->toArray());
}