Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Remember me #136

Closed
wants to merge 3 commits into from

6 participants

@Danielss89
Owner

Follows the principles of this blog post: http://jaspan.com/improved_persistent_login_cookie_best_practice

It seems that this has some changes from my refactor of the redirect param. Just ignore this.

Notice: Roderik dit not do any of this, it seems that i've commited with his email

@Danielss89
Owner

I dont think the names for some of the functions are good. If anyone have some better names just throw them at me!

@pensiero

Any news? How is it going here? I think this is a really important feature and if I can help in some way, even if i don't know a lot, tell me.

@Danielss89
Owner

It should be ready to merge. Waiting for @EvanDotPro

@pdobrigkeit

Hey,

I had the same idea that it would be a cool idea to have such an adapter. My approach would have been a little different though. But I just submitted a pull request to make the authentication adapters configurable, which would allow the DB adapter and the Cookie adapter to live side by side. Maybe that would help.

src/ZfcUser/Controller/UserController.php
((21 lines not shown))
);
}
$form->setData($request->getPost());
if (!$form->isValid()) {
+ die(var_dump($form->getMessages()));

My guess would be this has to be removed ;)

@Danielss89 Owner

Haha yeah probably :D wtf..

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@pdobrigkeit

Hey Daniel,

i used your pull request as the base to make a drop in module for ZfcUser which offers the remember me functionality. It requires much less changes to the ZfcUser. Maybe you want to check it out?

This pull request would be necessary for the new chains of adapters:
#163

And the module is at:
https://github.com/goalio/GoalioRememberMe

There is still some work to be done, but I think it is a good start and doesn't mess up so much of the original controller code. There are still some things missing, for example it is not checked right away if a cookie is present, but I would move that to either a controller helper or a view helper, because one is not always starting with the login form and still might want to show changes to the UI?

@rubera

Hey!

Really need this functionality. Is it going to be merged?

@pensiero

Pleeease someone merge this pull! Me and my users have to login after few seconds, and it's very tedious :(

@akrabat
Owner

@pdobrigkeit's module should now work.

@akrabat akrabat closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Sep 9, 2012
  1. @Danielss89

    initial remember me

    Danielss89 authored
Commits on Sep 14, 2012
  1. @roderik

    Modifications

    roderik authored
Commits on Oct 12, 2012
  1. @Danielss89
This page is out of date. Refresh to see the latest.
View
20 Module.php
@@ -62,10 +62,12 @@ public function getServiceConfig()
{
return array(
'invokables' => array(
- 'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db',
- 'ZfcUser\Authentication\Storage\Db' => 'ZfcUser\Authentication\Storage\Db',
- 'ZfcUser\Form\Login' => 'ZfcUser\Form\Login',
- 'zfcuser_user_service' => 'ZfcUser\Service\User',
+ 'ZfcUser\Authentication\Adapter\Db' => 'ZfcUser\Authentication\Adapter\Db',
+ 'ZfcUser\Authentication\Adapter\Cookie' => 'ZfcUser\Authentication\Adapter\Cookie',
+ 'ZfcUser\Authentication\Storage\Db' => 'ZfcUser\Authentication\Storage\Db',
+ 'ZfcUser\Form\Login' => 'ZfcUser\Form\Login',
+ 'zfcuser_user_service' => 'ZfcUser\Service\User',
+ 'zfcuser_rememberme_service' => 'ZfcUser\Service\RememberMe',
),
'factories' => array(
@@ -144,6 +146,16 @@ public function getServiceConfig()
$mapper->setHydrator(new Mapper\UserHydrator());
return $mapper;
},
+
+ 'zfcuser_rememberme_mapper' => function ($sm) {
+ $options = $sm->get('zfcuser_module_options');
+ $mapper = new Mapper\RememberMe;
+ $mapper->setDbAdapter($sm->get('zfcuser_zend_db_adapter'));
+ $entityClass = new Entity\RememberMe;
+ $mapper->setEntityPrototype(new $entityClass);
+ $mapper->setHydrator(new Mapper\RememberMeHydrator());
+ return $mapper;
+ },
),
);
}
View
10 config/zfcuser.global.php.dist
@@ -147,6 +147,16 @@ $settings = array(
//'logout_redirect_route' => 'zfcuser/login',
/**
+ * Remember me cookie expire time
+ *
+ * How long will the user be remembered for, in seconds?
+ *
+ * Default value: 2592000 seconds = 30 days
+ * Accepted values: the number of seconds the user should be remembered
+ */
+ //'cookie_expire' => 2592000,
+
+ /**
* Password Security
*
* DO NOT CHANGE THE PASSWORD HASH SETTINGS FROM THEIR DEFAULTS
View
12 data/schema.sql
@@ -5,4 +5,14 @@ CREATE TABLE user
email VARCHAR(255) DEFAULT NULL UNIQUE,
display_name VARCHAR(50) DEFAULT NULL,
password VARCHAR(128) NOT NULL
-) ENGINE=InnoDB;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+CREATE TABLE remember_me (
+ sid VARCHAR(16) NOT NULL,
+ token VARCHAR(16) NOT NULL,
+ user_id INTEGER(11) NOT NULL,
+ UNIQUE KEY sid (sid,token,user_id)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+ALTER TABLE remember_me
+ ADD CONSTRAINT remember_me FOREIGN KEY (user_id) REFERENCES user (user_id) ON DELETE CASCADE ON UPDATE CASCADE;
View
4 src/ZfcUser/Authentication/Adapter/AdapterChainServiceFactory.php
@@ -10,7 +10,9 @@ class AdapterChainServiceFactory implements FactoryInterface
public function createService(ServiceLocatorInterface $serviceLocator)
{
$chain = new AdapterChain;
- $adapter = $serviceLocator->get('ZfcUser\Authentication\Adapter\Db');
+ $session = new \Zend\Session\Container('zfcuser');
+ $adapter = (\ZfcUser\Service\RememberMe::getCookie() && !$session->offsetGet('forceRelogin')) ? 'ZfcUser\Authentication\Adapter\Cookie' : 'ZfcUser\Authentication\Adapter\Db';
+ $adapter = $serviceLocator->get($adapter);
$chain->getEventManager()->attach('authenticate', array($adapter, 'authenticate'));
return $chain;
}
View
124 src/ZfcUser/Authentication/Adapter/Cookie.php
@@ -0,0 +1,124 @@
+<?php
+
+namespace ZfcUser\Authentication\Adapter;
+
+use Zend\Authentication\Result as AuthenticationResult;
+use Zend\ServiceManager\ServiceManagerAwareInterface;
+use Zend\ServiceManager\ServiceManager;
+use Zend\Stdlib\RequestInterface as Request;
+use Zend\Stdlib\ResponseInterface as Response;
+use ZfcUser\Authentication\Adapter\AdapterChainEvent as AuthEvent;
+
+class Cookie extends AbstractAdapter implements ServiceManagerAwareInterface
+{
+ protected $userMapper;
+
+ protected $rememberMeMapper;
+
+ protected $serviceManager;
+
+ protected $rememberMeService;
+
+ public function authenticate(AuthEvent $e)
+ {
+ if ($this->isSatisfied()) {
+ $storage = $this->getStorage()->read();
+ $e->setIdentity($storage['identity'])
+ ->setCode(AuthenticationResult::SUCCESS)
+ ->setMessages(array('Authentication successful.'));
+ return;
+ }
+
+ $cookie = explode("\n", $_COOKIE['remember_me']);
+
+ $rememberMe = $this->getRememberMeMapper()->findByIdSerie($cookie[0], $cookie[1]);
+
+ if(!$rememberMe)
+ return false;
+
+ if($rememberMe->getToken() !== $cookie[2])
+ {
+ // H4x0r
+ // @TODO: Inform user of theft, change password?
+ $this->getRememberMeMapper()->removeAll($cookie[0]);
+ $this->setSatisfied(false);
+ return false;
+ }
+
+ $userObject = $this->getUserMapper()->findById($cookie[0]);
+
+ $this->getRememberMeService()->updateSerie($rememberMe);
+
+ // Success!
+ $e->setIdentity($userObject->getId());
+ $this->setSatisfied(true);
+ $storage = $this->getStorage()->read();
+ $storage['identity'] = $e->getIdentity();
+ $this->getStorage()->write($storage);
+ $e->setCode(AuthenticationResult::SUCCESS)
+ ->setMessages(array('Authentication successful.'));
+
+ $session = new \Zend\Session\Container('zfcuser');
+ $session->offsetSet("cookieLogin", true);
+ }
+
+ /**
+ * Retrieve service manager instance
+ *
+ * @return ServiceManager
+ */
+ public function getServiceManager()
+ {
+ return $this->serviceManager;
+ }
+
+ /**
+ * Set service manager instance
+ *
+ * @param ServiceManager $locator
+ * @return void
+ */
+ public function setServiceManager(ServiceManager $serviceManager)
+ {
+ $this->serviceManager = $serviceManager;
+ }
+
+ public function setRememberMeMapper($rememberMeMapper)
+ {
+ $this->rememberMeMapper = $rememberMeMapper;
+ }
+
+ public function getRememberMeMapper()
+ {
+ if (null === $this->rememberMeMapper) {
+ $this->rememberMeMapper = $this->getServiceManager()->get('zfcuser_rememberme_mapper');
+ }
+ return $this->rememberMeMapper;
+ }
+
+ public function setUserMapper($userMapper)
+ {
+ $this->userMapper = $userMapper;
+ }
+
+ public function getUserMapper()
+ {
+ if (null === $this->userMapper) {
+ $this->userMapper = $this->getServiceManager()->get('zfcuser_user_mapper');
+ }
+ return $this->userMapper;
+ }
+
+ public function setRememberMeService($rememberMeService)
+ {
+ $this->rememberMeService = $rememberMeService;
+ }
+
+ public function getRememberMeService()
+ {
+ if (null === $this->rememberMeService) {
+ $this->rememberMeService = $this->getServiceManager()->get('zfcuser_rememberme_service');
+ }
+ return $this->rememberMeService;
+ }
+}
View
8 src/ZfcUser/Authentication/Adapter/Db.php
@@ -89,6 +89,14 @@ public function authenticate(AuthEvent $e)
$this->getStorage()->write($storage);
$e->setCode(AuthenticationResult::SUCCESS)
->setMessages(array('Authentication successful.'));
+
+ /**
+ * If the user has first logged in with a cookie,
+ * but afterwords login with identity/credential
+ * we remove the "cookieLogin" session.
+ */
+ $session = new \Zend\Session\Container('zfcuser');
+ $session->offsetSet("cookieLogin", false);
}
protected function updateUserPasswordHash($userObject, $password, $bcrypt)
View
102 src/ZfcUser/Controller/UserController.php
@@ -12,6 +12,8 @@
class UserController extends AbstractActionController
{
+ protected $rememberMeService;
+
/**
* @var UserService
*/
@@ -48,12 +50,15 @@ class UserController extends AbstractActionController
*/
protected $options;
+ protected $sessionHandler;
+
/**
* User page
*/
public function indexAction()
{
if (!$this->zfcUserAuthentication()->hasIdentity()) {
+ $this->getSessionHandler()->offsetSet("redirect", $this->url()->fromRoute("zfcuser"));
return $this->redirect()->toRoute('zfcuser/login');
}
return new ViewModel();
@@ -64,19 +69,16 @@ public function indexAction()
*/
public function loginAction()
{
+ if($this->getRememberMeService()->getCookie() && !$this->getSessionHandler()->offsetGet('forceRelogin'))
+ return $this->forward()->dispatch('zfcuser', array('action' => 'authenticate'));
+
$request = $this->getRequest();
$form = $this->getLoginForm();
- if ($this->getOptions()->getUseRedirectParameterIfPresent() && $request->getQuery()->get('redirect')) {
- $redirect = $request->getQuery()->get('redirect');
- } else {
- $redirect = false;
- }
-
if (!$request->isPost()) {
return array(
'loginForm' => $form,
- 'redirect' => $redirect,
+ 'forceRelogin' => $this->getSessionHandler()->offsetGet('forceRelogin')
);
}
@@ -84,7 +86,7 @@ public function loginAction()
if (!$form->isValid()) {
$this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage($this->failedLoginMessage);
- return $this->redirect()->toUrl($this->url('zfcuser')->fromRoute('zfcuser/login').($redirect ? '?redirect='.$redirect : ''));
+ return $this->redirect()->toUrl($this->url('zfcuser')->fromRoute('zfcuser/login'));
}
// clear adapters
@@ -97,6 +99,13 @@ public function loginAction()
public function logoutAction()
{
$this->zfcUserAuthentication()->getAuthAdapter()->resetAdapters();
+
+ $user = $this->zfcUserAuthentication()->getAuthService()->getIdentity();
+ $cookie = explode("\n", $this->getRememberMeService()->getCookie());
+ $this->getRememberMeService()->removeSerie($user->getId(), $cookie[1]);
+ $this->getRememberMeService()->removeCookie();
+ $this->getSessionHandler()->offsetUnset('cookieLogin');
+
$this->zfcUserAuthentication()->getAuthService()->clearIdentity();
$redirect = ($this->getRequest()->getPost()->get('redirect')) ? $this->getRequest()->getPost()->get('redirect') : false;
@@ -113,12 +122,12 @@ public function logoutAction()
*/
public function authenticateAction()
{
- if ($this->zfcUserAuthentication()->getAuthService()->hasIdentity()) {
+ if ($this->zfcUserAuthentication()->getAuthService()->hasIdentity() && !$this->getSessionHandler()->offsetGet('forceRelogin')) {
return $this->redirect()->toRoute($this->getOptions()->getLoginRedirectRoute());
}
$request = $this->getRequest();
$adapter = $this->zfcUserAuthentication()->getAuthAdapter();
- $redirect = $request->getPost()->get('redirect') ? $request->getPost()->get('redirect') : false;
+
$result = $adapter->prepareForAuthentication($request);
@@ -132,10 +141,23 @@ public function authenticateAction()
if (!$auth->isValid()) {
$this->flashMessenger()->setNamespace('zfcuser-login-form')->addMessage($this->failedLoginMessage);
$adapter->resetAdapters();
- return $this->redirect()->toUrl($this->url()->fromRoute('zfcuser/login').($redirect ? '?redirect='.$redirect : ''));
+ return $this->redirect()->toUrl($this->url()->fromRoute('zfcuser/login'));
+ }
+
+ if (isset($_POST['remember_me']) && $_POST['remember_me'] == 1) {
+ $user = $this->zfcUserAuthentication()->getIdentity();
+ $this->getRememberMeService()->createSerie($user->getId());
+ }
+
+ $redirect = false;
+ if($this->getSessionHandler()->offsetExists("redirect"))
+ {
+ $redirect = $this->getSessionHandler()->offsetGet("redirect");
+ $this->getSessionHandler()->offsetUnset("redirect");
}
if ($this->getOptions()->getUseRedirectParameterIfPresent() && $redirect) {
+
return $this->redirect()->toUrl($redirect);
}
@@ -157,13 +179,7 @@ public function registerAction()
$service = $this->getUserService();
$form = $this->getRegisterForm();
- if ($this->getOptions()->getUseRedirectParameterIfPresent() && $request->getQuery()->get('redirect')) {
- $redirect = $request->getQuery()->get('redirect');
- } else {
- $redirect = false;
- }
-
- $redirectUrl = $this->url()->fromRoute('zfcuser/register') . ($redirect ? '?redirect=' . $redirect : '');
+ $redirectUrl = $this->url()->fromRoute('zfcuser/register');
$prg = $this->prg($redirectUrl, true);
if ($prg instanceof Response) {
@@ -172,7 +188,6 @@ public function registerAction()
return array(
'registerForm' => $form,
'enableRegistration' => $this->getOptions()->getEnableRegistration(),
- 'redirect' => $redirect,
);
}
@@ -183,7 +198,6 @@ public function registerAction()
return array(
'registerForm' => $form,
'enableRegistration' => $this->getOptions()->getEnableRegistration(),
- 'redirect' => $redirect,
);
}
@@ -196,17 +210,25 @@ public function registerAction()
}
$post['credential'] = $post['password'];
$request->setPost(new Parameters($post));
+
return $this->forward()->dispatch('zfcuser', array('action' => 'authenticate'));
}
- // TODO: Add the redirect parameter here...
- return $this->redirect()->toUrl($this->url()->fromRoute('zfcuser/login') . ($redirect ? '?redirect='.$redirect : ''));
+ return $this->redirect()->toUrl($this->url()->fromRoute('zfcuser/login'));
}
/**
* Change the users password
*/
- public function changepasswordAction() {
+ public function changepasswordAction()
+ {
+ if(!$this->zfcUserAuthentication()->hasIdentity() OR $this->getSessionHandler()->offsetGet('cookieLogin'))
+ {
+ $this->getSessionHandler()->offsetSet('redirect', $this->url()->fromRoute('zfcuser/changeemail'));
+ $this->getSessionHandler()->offsetSet('forceRelogin', true);
+ return $this->redirect()->toRoute("zfcuser/login");
+ }
+
$form = $this->getChangePasswordForm();
$prg = $this->prg('zfcuser/changepassword');
@@ -248,6 +270,13 @@ public function changepasswordAction() {
public function changeEmailAction()
{
+ if(!$this->zfcUserAuthentication()->hasIdentity() OR $this->getSessionHandler()->offsetGet('cookieLogin'))
+ {
+ $this->getSessionHandler()->offsetSet('redirect', $this->url()->fromRoute('zfcuser/changeemail'));
+ $this->getSessionHandler()->offsetSet('forceRelogin', true);
+ return $this->redirect()->toRoute("zfcuser/login");
+ }
+
$form = $this->getChangeEmailForm();
$request = $this->getRequest();
$request->getPost()->set('identity', $this->getUserService()->getAuthService()->getIdentity()->getEmail());
@@ -403,4 +432,31 @@ public function setChangeEmailForm($changeEmailForm)
$this->changeEmailForm = $changeEmailForm;
return $this;
}
+
+ public function getSessionHandler()
+ {
+ if(!$this->sessionHandler)
+ {
+ $this->sessionHandler = new \Zend\Session\Container('zfcuser');
+ }
+ return $this->sessionHandler;
+ }
+
+ public function setSessionHandler($sessionHandler)
+ {
+ $this->sessionHandler = $sessionHandler;
+ }
+
+ public function setRememberMeService($rememberMeService)
+ {
+ $this->rememberMeService = $rememberMeService;
+ }
+
+ public function getRememberMeService()
+ {
+ if (!$this->rememberMeService) {
+ $this->rememberMeService = $this->getServiceLocator()->get('zfcuser_rememberme_service');
+ }
+ return $this->rememberMeService;
+ }
}
View
42 src/ZfcUser/Entity/RememberMe.php
@@ -0,0 +1,42 @@
+<?php
+
+namespace ZfcUser\Entity;
+
+class RememberMe
+{
+ protected $sid;
+
+ protected $token;
+
+ protected $user_id;
+
+ public function getSid()
+ {
+ return $this->sid;
+ }
+
+ public function getToken()
+ {
+ return $this->token;
+ }
+
+ public function setSid($sid)
+ {
+ $this->sid = $sid;
+ }
+
+ public function setToken($token)
+ {
+ $this->token = $token;
+ }
+
+ public function setUserId($user_id)
+ {
+ $this->user_id = $user_id;
+ }
+
+ public function getUserId()
+ {
+ return $this->user_id;
+ }
+}
View
8 src/ZfcUser/Form/Base.php
@@ -76,10 +76,10 @@ public function __construct()
}
$submitElement = new Element\Button('submit');
- $submitElement
- ->setLabel('Submit')
- ->setAttributes(array(
- 'type' => 'submit',
+ $submitElement
+ ->setLabel('Submit')
+ ->setAttributes(array(
+ 'type' => 'submit',
));
$this->add($submitElement, array(
View
10 src/ZfcUser/Form/Login.php
@@ -37,7 +37,7 @@ public function __construct($name = null, AuthenticationOptionsInterface $option
$label = (!empty($label) ? $label . ' or ' : '') . ucfirst($mode);
}
$emailElement->setLabel($label);
- //
+
$this->add(array(
'name' => 'credential',
'options' => array(
@@ -48,6 +48,14 @@ public function __construct($name = null, AuthenticationOptionsInterface $option
),
));
+ $this->add(array(
+ 'type' => 'Zend\Form\Element\Checkbox',
+ 'name' => 'remember_me',
+ 'options' => array(
+ 'label' => 'Remember me',
+ )
+ ));
+
// @todo: Fix this
// 1) getValidator() is a protected method
// 2) i don't believe the login form is actually being validated by the login action
View
5 src/ZfcUser/Form/LoginFilter.php
@@ -39,6 +39,11 @@ public function __construct(AuthenticationOptionsInterface $options)
),
));
+ $this->add(array(
+ 'name' => 'remember_me',
+ 'required' => false,
+ ));
+
$this->getEventManager()->trigger('init', $this);
}
}
View
63 src/ZfcUser/Mapper/RememberMe.php
@@ -0,0 +1,63 @@
+<?php
+
+namespace ZfcUser\Mapper;
+
+use ZfcBase\Mapper\AbstractDbMapper;
+
+class RememberMe extends AbstractDbMapper
+{
+ protected $tableName = 'remember_me';
+
+ public function findById($userId)
+ {
+ $select = $this->getSelect()
+ ->from($this->tableName)
+ ->where(array('user_id' => $userId));
+
+ $entity = $this->select($select)->current();
+ $this->getEventManager()->trigger('find', $this, array('entity' => $entity));
+ return $entity;
+ }
+
+ public function findByIdSerie($userId, $serieId)
+ {
+ $select = $this->getSelect()
+ ->from($this->tableName)
+ ->where(array('user_id' => $userId, 'sid' => $serieId));
+
+ $entity = $this->select($select)->current();
+ $this->getEventManager()->trigger('find', $this, array('entity' => $entity));
+ return $entity;
+ }
+
+ public function updateSerie($entity)
+ {
+ $where = 'user_id = ' . $entity->getUserId() . ' && sid = "' . $entity->getSid() . '"';
+ $hydrator = new RememberMeHydrator;
+ return parent::update($entity, $where, $this->tableName, $hydrator);
+ }
+
+ public function createSerie($entity)
+ {
+ $hydrator = new RememberMeHydrator;
+ return parent::insert($entity, $this->tableName, $hydrator);
+ }
+
+ public function removeAll($userId)
+ {
+ $where = 'user_id = ' . $userId;
+ return parent::delete($where, $this->tableName);
+ }
+
+ public function remove($entity)
+ {
+ $where = 'user_id = ' . $entity->getUserId() . ' && sid = "' . $entity->getSid() . '" && token = "' . $entity->getToken() . '"';
+ return parent::delete($where, $this->tableName);
+ }
+
+ public function removeSerie($userId, $serieId)
+ {
+ $where = 'user_id = ' . $userId . ' && sid = "' . $serieId . '"';
+ return parent::delete($where, $this->tableName);
+ }
+}
View
19 src/ZfcUser/Mapper/RememberMeHydrator.php
@@ -0,0 +1,19 @@
+<?php
+
+namespace ZfcUser\Mapper;
+
+use Zend\Stdlib\Hydrator\ClassMethods;
+
+class RememberMeHydrator extends ClassMethods
+{
+ public function extract($object)
+ {
+ $data = parent::extract($object);
+ return $data;
+ }
+
+ public function hydrate(array $data, $object)
+ {
+ return parent::hydrate($data, $object);
+ }
+}
View
20 src/ZfcUser/Options/ModuleOptions.php
@@ -6,7 +6,8 @@
class ModuleOptions extends AbstractOptions implements
UserControllerOptionsInterface,
- UserServiceOptionsInterface
+ UserServiceOptionsInterface,
+ RememberMeOptionsInterface
{
/**
* Turn off strict options mode
@@ -79,6 +80,12 @@ class ModuleOptions extends AbstractOptions implements
protected $passwordCost = 14;
/**
+ * 30 days default
+ * @var int
+ */
+ protected $cookieExpire = 2592000;
+
+ /**
* @var array
*/
protected $formCaptchaOptions = array(
@@ -397,4 +404,15 @@ public function getFormCaptchaOptions()
{
return $this->formCaptchaOptions;
}
+
+ public function setCookieExpire($seconds)
+ {
+ $this->cookieExpire = $seconds;
+ return $this;
+ }
+
+ public function getCookieExpire()
+ {
+ return $this->cookieExpire;
+ }
}
View
16 src/ZfcUser/Options/RememberMeOptionsInterface.php
@@ -0,0 +1,16 @@
+<?php
+
+namespace ZfcUser\Options;
+
+interface RememberMeOptionsInterface
+{
+ /**
+ * @param int $seconds
+ */
+ public function setCookieExpire($seconds);
+
+ /**
+ * @return int
+ */
+ public function getCookieExpire();
+}
View
133 src/ZfcUser/Service/RememberMe.php
@@ -0,0 +1,133 @@
+<?php
+
+namespace ZfcUser\Service;
+
+use Zend\ServiceManager\ServiceManagerAwareInterface;
+use Zend\ServiceManager\ServiceManager;
+use ZfcBase\EventManager\EventProvider;
+use ZfcUser\Options\RememberMeOptionsInterface;
+use Zend\Math\Rand;
+
+class RememberMe extends EventProvider implements ServiceManagerAwareInterface
+{
+ protected $mapper, $options;
+
+ protected $serviceManager;
+
+ public function createToken($length = 16)
+ {
+ $rand = Rand::getBytes($length, true);
+ return $rand;
+ }
+
+ public function createSerieId($length = 16)
+ {
+ $rand = Rand::getBytes($length, true);
+ return $rand;
+ }
+
+ public function updateSerie($entity)
+ {
+ $rememberMe = $this->getMapper()->findByIdSerie($entity->getUserId(), $entity->getSid());
+ if($rememberMe){
+ // Update serie with new token
+ $token = $this->createToken();
+ $rememberMe->setToken($token);
+ $this->setCookie($rememberMe);
+ $this->getMapper()->updateSerie($rememberMe);
+ return $token;
+ }
+ return false;
+ }
+
+ public function createSerie($userId)
+ {
+ $token = $this->createToken();
+ $serieId = $this->createSerieId();
+
+ $rememberMe = new \ZfcUser\Entity\RememberMe;
+ $rememberMe->setUserId($userId);
+ $rememberMe->setSid($serieId);
+ $rememberMe->setToken($token);
+
+ if($this->setCookie($rememberMe))
+ {
+ $rememberMe = $this->getMapper()->createSerie($rememberMe);
+ return $rememberMe;
+ }
+
+ return false;
+ }
+
+ public function removeSerie($userId, $serieId)
+ {
+ $this->getMapper()->removeSerie($userId, $serieId);
+ }
+
+ public function removeCookie()
+ {
+ setcookie("remember_me", "", time() - 3600);
+ }
+
+ public static function getCookie()
+ {
+ return isset($_COOKIE['remember_me']) ? $_COOKIE['remember_me'] : false;
+ }
+
+ public function setCookie($entity)
+ {
+ $cookieLength = $this->getOptions()->getCookieExpire();
+ $cookieValue = $entity->getUserId() . "\n" . $entity->getSid() . "\n" . $entity->getToken();
+ return setcookie("remember_me", $cookieValue, time() + $cookieLength);
+ }
+
+ public function setMapper($mapper)
+ {
+ $this->mapper = $mapper;
+ }
+
+ public function getMapper()
+ {
+ if (null === $this->mapper) {
+ $this->mapper = $this->getServiceManager()->get('zfcuser_rememberme_mapper');
+ }
+ return $this->mapper;
+ }
+
+ /**
+ * Retrieve service manager instance
+ *
+ * @return ServiceManager
+ */
+ public function getServiceManager()
+ {
+ return $this->serviceManager;
+ }
+
+ /**
+ * Set service manager instance
+ *
+ * @param ServiceManager $locator
+ * @return User
+ */
+ public function setServiceManager(ServiceManager $serviceManager)
+ {
+ $this->serviceManager = $serviceManager;
+ return $this;
+ }
+
+
+ public function setOptions(RememberMeOptionsInterface $options)
+ {
+ $this->options = $options;
+ return $this;
+ }
+
+ public function getOptions()
+ {
+ if (!$this->options instanceof RememberMeOptionsInterface) {
+ $this->setOptions($this->getServiceManager()->get('zfcuser_module_options'));
+ }
+ return $this->options;
+ }
+}
View
7 view/zfc-user/user/login.phtml
@@ -18,6 +18,11 @@ $form->setAttribute('method', 'post');
<dt><?php echo $this->formLabel($form->get('credential')) ?></dt>
<dd><?php echo $this->formInput($form->get('credential')) ?></dd>
+ <?php if(!$this->forceRelogin): // If we force a relogin, it means that the user is allready being remembered ?>
+ <dt><?php echo $this->formLabel($form->get('remember_me')) ?></dt>
+ <dd><?php echo $this->formCheckbox($form->get('remember_me')) ?></dd>
+ <?php endif; ?>
+
<?php if ($this->redirect): ?>
<input type="hidden" name="redirect" value="<?php echo $this->redirect ?>" />
<?php endif ?>
@@ -27,4 +32,4 @@ $form->setAttribute('method', 'post');
<?php echo $this->form()->closeTag() ?>
-Not registered? <a href="<?php echo $this->url('zfcuser/register') . ($this->redirect ? '?redirect='.$this->redirect : '') ?>">Sign up!</a>
+Not registered? <a href="<?php echo $this->url('zfcuser/register') . ($this->redirect ? '?redirect='.$this->redirect : '') ?>">Sign up!</a>
Something went wrong with that request. Please try again.