Pull to refresh

Zend framework — туториал: авторизация

Reading time 6 min
Views 9.2K
Знаю что в сети много уже таких туториалов, но я сам так же знаю что ZF очень труден на старте, но потом… все ясно и легко.
Хотелось бы облегчить эту первую стадию тем кто еще только в начале пути.

Для авторизации нам потребуется конечно же готовая таблица пользователей — минимум два поля, userName и passwordMD5.
passwordMD5 — сразу понятно что хранит пароль в неявном виде, что бы его кто то не украл в один момент.

1. Делаем форму логина.



<?php

class Form_Login extends Zend_Form
{
  
  public function init()
  {

      // метод пост
      $this->setMethod('post');

      $this->addElement('text', 'userName', array(
      'label'   => 'Имя Пользователя:',      
      'filters'  => array('StringTrim')
      ));
      $el = $this->getElement('userName');
      $el->setRequired(true)
      ->addValidators(array(
      array('NotEmpty', true, array('messages' => array(
        'isEmpty' => 'имя пользователя обязательный пункт!',
      )))));
     

      $this->addElement('password', 'password', array(
      'label'   => 'Пароль:'
      ));
      $el = $this->getElement('password');

      $el->setRequired(true)->addValidators(array(
      array('NotEmpty', true, array('messages' => array(
        'isEmpty' => 'пароль не может быть пустым!',
      )))));

      $this->addElement('submit', 'login', array(

      'label'   => 'логин'
      ));    
  }
}


* This source code was highlighted with Source Code Highlighter.


Кладем этот класс в /application/forms(или куда душе угодно)

2. Контроллер для логина.
<?php
class LoginController extends Zend_Controller_Action
{
  
  public function preDispatch()
  {
    if (Zend_Auth::getInstance()->hasIdentity()) {
      return $this->_redirect('/');//вдруг уже залогинен, перенаправляем на главную
    }
  }
  

  public function indexAction()
  {

    $form = $this->_getLoginForm();
    
    if ($this->_request->isPost()) {
      $formData = $this->_request->getPost();

      if ($form->isValid($formData)) {

        $auth  = Zend_Auth::getInstance();
        $authAdapter = $this->_getAuthAdapter($formData['userName'],$formData['password']);
        $result = $auth->authenticate($authAdapter);
        if (!$result->isValid()) {
          // все неправильно
          $form->setDescription('Неправильные имя или пароль');
          $form->populate($formData);
          $this->view->form = $form;
          return $this->render('index'); // перерисуем форму
        }else{
          
          $currentUser = $authAdapter->getResultRowObject();
          Zend_Auth::getInstance()->getStorage()->write( $currentUser);//записали юзера в auth, теперь он везде доступен - только для чтения
            
          return $this->_redirect('/');//залогинился,редирект на главную
        }

      } else {
        $form->populate($formData);
      }
    }
    
    $this->view->form = $form;
  }

  protected function _getLoginForm()
  {
    require_once APPLICATION_PATH . '/forms/Login.php';
    return new Form_Login();
  }

  protected function _getAuthAdapter($userName, $userPassword)
  {
    $authAdapter = new Zend_Auth_Adapter_DbTable(
    $registry->dbAdapter,
    'user',
    'username',
    'passwordMD5',
    'MD5(?) AND status = "OK"'
    );
    $authAdapter->setIdentity($userName)->setCredential($userPassword);

    return $authAdapter;
  }

}
?>


* This source code was highlighted with Source Code Highlighter.


Registry::getInstance()->session — сессию создаем в bootstrap.php и аккуратно засовываем в наш объект registry.

$configuration = new Zend_Config(require APPLICATION_PATH . '/config/config.php');
$dbAdapter = Zend_Db::factory($configuration->database);
Zend_Db_Table_Abstract::setDefaultAdapter($dbAdapter);
$registry = Zend_Registry::getInstance();
$registry->configuration = $configuration;
$registry->dbAdapter   = $dbAdapter;
$registry->session = new Zend_Session_Namespace();


* This source code was highlighted with Source Code Highlighter.


Думаю разжевывать здесь нечего, все и так понятно. Думаю есть и другие способы авторизации, но меня устраивает этот полностью.

Запомни меня?


Для того что бы вашего юзера запомнила система нужно всего лишь добавить елемент на форме(сами знаете какой) и если юзер наш залогинелся вызвать такой код:

Zend_Session::rememberMe(1209600);//тут каждый сам решает для себя сколько нужно

После логина обращение к объекту юзера можно делать в любом месте кода таким образом:

$auth = Zend_Auth::getInstance()->getIdentity();

Но вот оно — когда вы попробуете изменить какое то свойство этого объекта и сохранить его сразу же получите такую обшибку —
Cannot save a Row unless it is connected

Получается мы записали объект в сессию, и после этого это уже просто объект и соединение с базой у него потеряно.

Для этого я сделал очень простое решение.
Создаем plugin класс:

<?php
class CheckLoginPlugin extends Zend_Controller_Plugin_Abstract
{
  protected $_userModel;

  public function dispatchLoopStartup(Zend_Controller_Request_Abstract $request){
    $auth = Zend_Auth::getInstance();
    $user = $auth->getIdentity();
        $model = $this->_getUserModel();
    $auth->getStorage()->write($model->getUserById($user->id));
   
  }

    public function _getUserModel(){
    if (null === $this->_userModel) {
      require_once APPLICATION_PATH . '/models/User.php';
      $this->_userModel = new Model_User();
    }
    return $this->_userModel;
  }

}
?>


* This source code was highlighted with Source Code Highlighter.


Подключаем плагин в bootstrap.php

require_once 'My/Plugin/CheckLoginPlugin.php';
$frontController->registerPlugin(new CheckLoginPlugin());


* This source code was highlighted with Source Code Highlighter.


Этот плагин просто обновляет объект из базы при каждом вызове страницы. Конечно можно это делать только по необходимости, кто как экономит, у меня спичек хватает :)

PS — пример конечно может содержать некотрые ошибки(логики), воспринимайте это как псевдокод, но при минимальных знаниях в пхп думаю это будет легко поправить.

так же можно сделать авторизацию для zend программы с использованием OpenID
Tags:
Hubs:
+7
Comments 16
Comments Comments 16

Articles