• Zend Framework 2 : Create Simple Login Authentication using AuthenticationService with rememberMe

    Zend Framework 2 : Create Simple Login Authentication using AuthenticationService with rememberMe?

    Silver Member Asked on August 23, 2016 in Zend Framework.
    Add Comment
  • 1 Answer(s)

    Authentication is the process of verifying that “you are who you say you are”. Zend Framework 2 has an AuthenticationService component that usefull to handle this. It can use Adapters, like DbTable, Digest, Http, and Ldap with Session Storage that can be save until time we need by rememberMe() function from Session Manager.


    For example, i have the following form like this to utilize rememberMe() function for authentication with DbTable adapter :

    1. Prepare a Login Form with this entity.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    //module/SanAuth/src/SanAuth/Model/User.php
    namespace SanAuth\Model;
    use Zend\Form\Annotation;
    /**
     * @Annotation\Hydrator("Zend\Stdlib\Hydrator\ObjectProperty")
     * @Annotation\Name("User")
     */
    class User
    {
        /**
         * @Annotation\Type("Zend\Form\Element\Text")
         * @Annotation\Required({"required":"true" })
         * @Annotation\Filter({"name":"StripTags"})
         * @Annotation\Options({"label":"Username:"})
         */
        public $username;
        
        /**
         * @Annotation\Type("Zend\Form\Element\Password")
         * @Annotation\Required({"required":"true" })
         * @Annotation\Filter({"name":"StripTags"})
         * @Annotation\Options({"label":"Password:"})
         */
        public $password;
        
        /**
         * @Annotation\Type("Zend\Form\Element\Checkbox")
         * @Annotation\Options({"label":"Remember Me ?:"})
         */
        public $rememberme;
        
        /**
         * @Annotation\Type("Zend\Form\Element\Submit")
         * @Annotation\Attributes({"value":"Submit"})
         */
        public $submit;
    }

    Create custom Auth Storage that extends Zend\Authentication\Storage.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    //module/SanAuth/src/SanAuth/Model/MyAuthStorage.php
    namespace SanAuth\Model;
    use Zend\Authentication\Storage;
    class MyAuthStorage extends Storage\Session
    {
        public function setRememberMe($rememberMe = 0, $time = 1209600)
        {
             if ($rememberMe == 1) {
                 $this->session->getManager()->rememberMe($time);
             }
        }
        
        public function forgetMe()
        {
            $this->session->getManager()->forgetMe();
        }
    }

    2. Register that into ServiceManager in Module class.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    //module/SanAuth/Module.php
    namespace SanAuth;
    use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
    use Zend\Authentication\Storage;
    use Zend\Authentication\AuthenticationService;
    use Zend\Authentication\Adapter\DbTable as DbTableAuthAdapter;
    class Module implements AutoloaderProviderInterface
    {
        public function getAutoloaderConfig(){/*common code*/}
        public function getConfig(){ /*common code*/}
        
        public function getServiceConfig()
        {
            return array(
                'factories'=>array(
            'SanAuth\Model\MyAuthStorage' => function($sm){
                return new \SanAuth\Model\MyAuthStorage('zf_tutorial'); 
            },
            
            'AuthService' => function($sm) {
                        //My assumption, you've alredy set dbAdapter
                        //and has users table with columns : user_name and pass_word
                        //that password hashed with md5
                $dbAdapter           = $sm->get('Zend\Db\Adapter\Adapter');
                        $dbTableAuthAdapter  = new DbTableAuthAdapter($dbAdapter,
                                                  'users','user_name','pass_word', 'MD5(?)');
                
                $authService = new AuthenticationService();
                $authService->setAdapter($dbTableAuthAdapter);
                        $authService->setStorage($sm->get('SanAuth\Model\MyAuthStorage'));
                 
                return $authService;
            },
                ),
            );
        }
    }

    3. Create the Auth Controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    //module/SanAuth/src/SanAuth/Controller/AuthController.php
    namespace SanAuth\Controller;
    use Zend\Mvc\Controller\AbstractActionController;
    use Zend\Form\Annotation\AnnotationBuilder;
    use Zend\View\Model\ViewModel;
    use SanAuth\Model\User;
    class AuthController extends AbstractActionController
    {
        protected $form;
        protected $storage;
        protected $authservice;
        
        public function getAuthService()
        {
            if (! $this->authservice) {
                $this->authservice = $this->getServiceLocator()
                                          ->get('AuthService');
            }
            
            return $this->authservice;
        }
        
        public function getSessionStorage()
        {
            if (! $this->storage) {
                $this->storage = $this->getServiceLocator()
                                      ->get('SanAuth\Model\MyAuthStorage');
            }
            
            return $this->storage;
        }
        
        public function getForm()
        {
            if (! $this->form) {
                $user       = new User();
                $builder    = new AnnotationBuilder();
                $this->form = $builder->createForm($user);
            }
            
            return $this->form;
        }
        
        public function loginAction()
        {
            //if already login, redirect to success page
            if ($this->getAuthService()->hasIdentity()){
                return $this->redirect()->toRoute('success');
            }
                    
            $form       = $this->getForm();
            
            return array(
                'form'      => $form,
                'messages'  => $this->flashmessenger()->getMessages()
            );
        }
        
        public function authenticateAction()
        {
            $form       = $this->getForm();
            $redirect = 'login';
            
            $request = $this->getRequest();
            if ($request->isPost()){
                $form->setData($request->getPost());
                if ($form->isValid()){
                    //check authentication...
                    $this->getAuthService()->getAdapter()
                                           ->setIdentity($request->getPost('username'))
                                           ->setCredential($request->getPost('password'));
                                           
                    $result = $this->getAuthService()->authenticate();
                    foreach($result->getMessages() as $message)
                    {
                        //save message temporary into flashmessenger
                        $this->flashmessenger()->addMessage($message);
                    }
                    
                    if ($result->isValid()) {
                        $redirect = 'success';
                        //check if it has rememberMe :
                        if ($request->getPost('rememberme') == 1 ) {
                            $this->getSessionStorage()
                                 ->setRememberMe(1);
                            //set storage again
                            $this->getAuthService()->setStorage($this->getSessionStorage());
                        }
                        $this->getAuthService()->getStorage()->write($request->getPost('username'));
                    }
                }
            }
            
            return $this->redirect()->toRoute($redirect);
        }
        
        public function logoutAction()
        {
            $this->getSessionStorage()->forgetMe();
            $this->getAuthService()->clearIdentity();
            
            $this->flashmessenger()->addMessage("You've been logged out");
            return $this->redirect()->toRoute('login');
        }
    }

    4. Create Success Controller

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //module/SanAuth/src/SanAuth/Controller/SuccessController.php
    namespace SanAuth\Controller;
    use Zend\Mvc\Controller\AbstractActionController;
    use Zend\View\Model\ViewModel;
    class SuccessController extends AbstractActionController
    {
        public function indexAction()
        {
            if (! $this->getServiceLocator()
                     ->get('AuthService')->hasIdentity()){
                return $this->redirect()->toRoute('login');
            }
            
            return new ViewModel();
        }
    }

    5. Register controller invokables, router, and view_manager into module.config.php

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    return array(
        'controllers' => array(
            'invokables' => array(
                'SanAuth\Controller\Auth' => 'SanAuth\Controller\AuthController',
                'SanAuth\Controller\Success' => 'SanAuth\Controller\SuccessController'
            ),
        ),
        'router' => array(
            'routes' => array(
                
                'login' => array(
                    'type'    => 'Literal',
                    'options' => array(
                        'route'    => '/auth',
                        'defaults' => array(
                            '__NAMESPACE__' => 'SanAuth\Controller',
                            'controller'    => 'Auth',
                            'action'        => 'login',
                        ),
                    ),
                    'may_terminate' => true,
                    'child_routes' => array(
                        'process' => array(
                            'type'    => 'Segment',
                            'options' => array(
                                'route'    => '/[:action]',
                                'constraints' => array(
                                    'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                                    'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                                ),
                                'defaults' => array(
                                ),
                            ),
                        ),
                    ),
                ),
                
                'success' => array(
                    'type'    => 'Literal',
                    'options' => array(
                        'route'    => '/success',
                        'defaults' => array(
                            '__NAMESPACE__' => 'SanAuth\Controller',
                            'controller'    => 'Success',
                            'action'        => 'index',
                        ),
                    ),
                    'may_terminate' => true,
                    'child_routes' => array(
                        'default' => array(
                            'type'    => 'Segment',
                            'options' => array(
                                'route'    => '/[:action]',
                                'constraints' => array(
                                    'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
                                    'action'     => '[a-zA-Z][a-zA-Z0-9_-]*',
                                ),
                                'defaults' => array(
                                ),
                            ),
                        ),
                    ),
                ),
                
            ),
        ),
        'view_manager' => array(
            'template_path_stack' => array(
                'SanAuth' => __DIR__ . '/../view',
            ),
        ),
    );

    6. Create a login view :

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    //module/SanAuth/view/san-auth/auth/login.phtml
    $form = $this->form;
    $form->setAttribute('action', $this->url(
        'login/process',
        array(
            'action'     => 'authenticate',
        )
    ));
    $form->prepare();
    echo $this->form()->openTag($form);
    echo $this->formCollection($form);
    echo $this->form()->closeTag();
    if ($this->messages){
        echo '<ul>';
        foreach($this->messages as $message)
        {
            echo '<li>'.$message.'</li>';
        }
        echo '</ul>';
    }

    7. The success view

    1
    2
    3
    4
    5
    <!-- //module/SanAuth/view/san-auth/success/index.phtml -->
    Login Success.
    <br />
    <a href="<?php echo $this->url('login/process', array('action'=>'logout')); ?>">Logout</a>

    Btw, I publish this sourcecode into my github account : https://github.com/samsonasik/SanAuth .

    Silver Member Answered on August 23, 2016.
    Add Comment
  • Your Answer

    By posting your answer, you agree to the privacy policy and terms of service.