Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.

9 января, 2010
yii_game_site_auth

Приветствую всех! Эта статья – продолжение цикла о создании игрового сайта с использованием PHP фреймворка Yii.

Сегодня мы займемся ограничением доступа к административной части сайта. У вас может возникнуть вполне закономерный вопрос: «Почему именно ею? Ведь в предыдущих частях мы только создали базу данных, на сайте нет ни одной рабочей страницы.»

Всё правильно, но Yii имеет некоторые особенности. Код, который генерирует консольная утилита при создании контроллеров, автоматически использует встроенную библиотеку авторизации. Кроме того, в стандартном приложении, которое мы в прошлый раз создали командой yiic webapp есть все необходимые компоненты для аутентификации и авторизации пользователей.

От нас требуется только связать этот код с нашей базой данных. Т.е. кода нам нужно написать совсем немного.

Прежде всего, рассмотрим как вообще работает эта библиотека.

Основная её часть – это компонент реализующий интерфейс IWebUser. Доступ к нему можно получить так:

Yii::app()->user

Используя этот компонент (экземпляр класса СWebUser) можно проверить выполнил ли пользователь вход, получить его данные и т.п.

Для того, чтобы аутентифицировать пользователя мы должны определить класс, в котором будет находится код, проверяющий имя и пароль. Этот класс уже создан и находится он в файле protected\components\UserIdentity.php, но по-умолчанию имя и пароль записаны в обычном массиве, а нам нужно хранить их в базе данных.

Поэтому мы перепишем метод authenticate.

  1. 'db'=>array(
  2.     'connectionString'=>'mysql:host=localhost;dbname=имя_бд',
  3.     'username'=>'имя_пользователя',
  4.     'password'=>'пароль',
  5.     'charset'=>'utf8',
  6. ),

И выполняем в консоли две команды.

>> yiic shell
>> model Users ygs_users

После этого у нас появится файл protected\models\Users.php.

Тут же мы можем создать стандартный код для выполнения CRUD операций

>> crud Users

В результате появятся контроллер (protected\controllers\UsersController.php) и папка с файлами представлений (protected\views\users\). Сейчас мы их трогать не будем, они понадобятся в дальнейшем, когда мы будем заниматься админкой сайта.

А сейчас создадим ещё один контроллер.

>> controller Dashboard

Это не обязательно, но я не хочу чтобы форма входа относилась к контроллеру SiteController, который был создан по-умолчанию.

Перенесем форму входа в контроллер Dashboard, и заодно разберем каким образом выполняется аутентификация и авторизация пользователей.

Сама форма находится в файле protected\views\site\login.php. Поэтому просто перемещаем его в папку protected\views\dashboard\.

Настраиваем контроллер Dashboard.

Добавляем метод (на самом деле вручную писать код не нужно, можно просто скопировать метод из файла SiteController.php)

  1. public function filters()
  2. {
  3.     return array(
  4.         'accessControl', // perform access control for CRUD operations
  5.     );
  6. }

Теперь перед обращением к любому из методов контроллера фреймворк будет проверять имеет ли посетитель достаточные права.

Добавляем метод

  1. public function accessRules()
  2. {
  3.     return array(
  4.         array('allow',
  5.             'actions'=>array('login','logout'),
  6.             'users'=>array('*'),
  7.         ),
  8.         array('allow',
  9.             'actions'=>array('index'),
  10.             'users'=>array('admin'),
  11.         ),
  12.         array('deny',  // deny all users
  13.             'users'=>array('*'),
  14.         ),
  15.     );
  16. }

В нём находится массив с правилами, которые указывают, что общедоступными являются только методы actionLogin() и actionLogout(). Первый показывает форму входа, второй – выполняет выход из системы.

Копируем и эти два метода

  1. /**
  2.  * Формирует страницу с формой входа
  3.  */
  4. public function actionLogin()
  5. {
  6.     $form=new LoginForm;
  7.     // collect user input data
  8.     if(isset($_POST['LoginForm']))
  9.     {
  10.         $form->attributes=$_POST['LoginForm'];
  11.         // validate user input and redirect to previous page if valid
  12.         if($form->validate())
  13.             $this->redirect(Yii::app()->user->returnUrl);
  14.     }
  15.     // display the login form
  16.     $this->render('login',array('form'=>$form));
  17. }
  18.  
  19. /**
  20.  * Выход из панели управления и переход на главную страницу.
  21.  */
  22. public function actionLogout()
  23. {
  24.     Yii::app()->user->logout();
  25.     $this->redirect(Yii::app()->homeUrl);
  26. }

С методом actionLogout(), надеюсь, всё понятно. Сначала завершаем сессию (метод logout()), затем отправляем редирект на домашнюю страницу.

Метод actionLogin() немного сложнее. Здесь мы создаём объект типа LoginForm. Класс LoginForm создан автоматически и находится в файле (protected\models\LoginForm.php).

Этот класс содержит метод authenticate, который вызывается для проверки поля с паролем. И именно в этом методе создаётся объект типа UserIdentity, который содержит нашу логику проверки имени и пароля. В этом же методе находится вызов Yii::app()->user->login(…).

Подводя итог, запишем порядок аутентификации.

1) Посетитель вводит имя / пароль и нажимает кнопку «Войти».

2) Фреймворк создает DashboardController и вызывает его метод actionLogin.

3) В методе actionLogin создается экземпляр класса LoginForm и вызывается его метод validate.

4) Фреймворк перебирает все правила, указанные в массиве, который возвращает метод rules. Одно из этих правил выглядит так
array('password', 'authenticate')
Это означает, что должен быть вызван метод LoginForm::authenticate(…).

5) LoginForm:: authenticate(…) создаёт экземпляр класса UserIdentity и вызывает его метод authenticate (в котором находится наша логика проверки имени и пароля).

6) Если все проверки прошли успешно, вызывается Yii::app()->user->login(…). Аутентификация завершена.

На первый взгляд, выглядит немного запутанно, но это потому, что используется несколько библиотек фреймворка одновременно. В частности, используется библиотека для проверки данных форм.

Тут я хочу отметить одно из отличий Yii от CodeIgniter. В состав Yii входит довольно много библиотек, и генератор кода их активно использует. Поэтому если библиотеки вас устраивают, вы выигрываете, т.к. значительная часть кода будет написана за вас. С другой стороны, если вы хотите использовать другую библиотеку, то эту часть кода придется переписать.

В следующей части мы рассмотрим работу с жанрами игр.

Все разделы цикла.

  1. Yii PHP framework: создаём игровой сайт. Часть 1. Постановка задачи.
  2. Yii PHP framework: создаём игровой сайт. Часть 2. База данных и установка фреймворка.
  3. Yii PHP framework: создаём игровой сайт. Часть 3. Аутентификация.
  4. Yii PHP framework: создаём игровой сайт. Часть 4. Работа с жанрами игр.
  5. Yii PHP framework: создаём игровой сайт. Часть 5. Импорт игр.
  6. Yii PHP framework: создаём игровой сайт. Часть 6. Формируем страницы игр и жанров.
  7. Yii PHP framework: создаём игровой сайт. Часть 7. Работа с JavaScript и страницы игр.
  8. Yii PHP framework: создаём игровой сайт. Часть 8. Создаём виджеты.
  9. Yii PHP framework: создаём игровой сайт. Часть 9. Поиск ошибок.
  10. Yii PHP framework: создаём игровой сайт. Часть 10. Панель управления.
  11. Yii PHP framework: создаём игровой сайт. Часть 11. Человекопонятные URL.
  12. Архив с исходниками

Постовой

Рекомендуем: абонентское кадровое обслуживание ООО и ИП. От профессионалов

Понравилась статья? Подписывайтесь на продолжение rss link !

Или на мой твиттер twitter link

]]>

Добавьте эту страницу в google.com bobrdobr.ru del.icio.us technorati.com linkstore.ru news2.ru rumarkz.ru memori.ru moemesto.ru

]]>

Опубликовано в PHP, Web разработка, Yii Комментарии (24) »

]]>

Комментарии (24)

Вы можете отслеживать обсуждение записи с помощью RSS 2.0 rss link

Вы также можете оставить комментарий, или трекбек с Вашего сайта.

]]>
  1. bersy

    т.к намечается цикл статей, можете указывать теги, скажем Yii или хотя бы более общий framework, что бы в последствии облегчить навигацию? просто категории PHP, Web разработка у вас довольно объемные – можно затеряться :)

    благодарю!

  2. Sam

    «Сейчас мы их трогать не будет» → «будем»
    «Теперь перед обращение» → «обращением»

    Ссылки лучше сразу давать на русскую документацию: http://yiiframework.ru/doc/guide/topics.auth.

    Стоит также отметить, что есть возможность более гибкой настройки прав через RBAC, хотя в этом случае она не понадобится.

    • Спасибо за исправления!

      Ссылки на русскую документацию – это правильно, но я пользовался всё время английским и он для меня привычнее.
      Я, наверное, сделаю отдельный анонс русской документации.

      RBAC. Учту замечание. Просто очень сложно выбрать о чем рассказывать, а что пропустить. С библиотекой для работы с БД ещё сложнее. Она объемная и запросы можно сформировать несколькими способами. В общем, посмотрим как получится, в любом случае уже есть переведённая документация ;)

  3. Спасибо за детальное описание, все понятно излагаете! Жду следующего поста по этой теме!

  4. alex

    ну и в дополнении можно сказать, что при использовании filters() и accessRules() ограничения будут действовать только на контроллер, в котором они определены.

    Поэтому, чтобы не плодить код, просто расширяем его.

  5. будут действовать только на контроллер, в котором они определены

    Безусловно, ведь в accessRules мы перечисляем названия методов контроллера (без приставки action), если бы была возможность ставить правила для методов другого контроллера, то запутаться было бы очень легко ;)

  6. Максим

    У меня возникают проблемы с выполнением команд:

    >> yiic shell
    >> model Users ygs_users

    а именно:

    >> model Users ygs_users
    Warning: the table 'ygs_users' does not exist in the database.
    generate models/Users.php
    generate fixtures/ygs_users.php
    generate unit/UsersTest.php
    The following model classes are successfully generated:
    Users
    If you have a 'db' database connection, you can test these models now with:
    $model=Users::model()->find();
    print_r($model);
    >> crud Users
    Error: Table "ygs_users" does not have a primary key.

    Для создания таблиц использовал 'dump.sql' из архива.
    P.S.Использую Yii v1.1.0 на Денвере

  7. Одиночка Айс

    У меня не получается использовать контроллер Dashboard (в моем случае admin_panel). Yii ругается на то, что SiteController не может найти запрашиваемый вид login:

    SiteController cannot find the requested view "login".

    Я так понимаю, что он теряет управление, Admin_panelController еще не может вступить в права управления

    • Проверьте файл protected/config/main.php
      в нём должны быть такие настройки
      'user'=>array(
      'allowAutoLogin'=>true,
      'loginUrl'=>array('dashboard/login'),
      ),
      Кроме того, в папке protected/views/dashboard/ должен быть файл login.php.
      И метод actionLogin в файле protected/controllers/DashboardController.php.

  8. ditex

    стабильно выдаёт


    Fatal error: Call to a member function getDb() on a non-object in C:\WebServers\
    home\localhost\www\framework\cli\commands\shell\ModelCommand.php on line 260

    В чём может быть проблема?

    • Эта ошибка вылезает когда вы yiic запускаете?
      Пока в голову приходят два варианта:
      1) неправильные параметры подключения к базе (первый листинг в этой статье).
      2) если у вас установлена vista или семёрка, доступ на запись на диск C может быть ограничен, можно попробовать запустить консоль от имени администратора.

  9. ditex

    Ввожу yiic shell cd.. и всё нормально, но после ввода model Users ygs_users выдаёт эту ошибку. Перепроверил имя БД и логин, пароль – всё верно. Из под Админа в семёрке запускаю.

    ЗЫ. Ещё одна строчка ошибки (после line 260), в первый раз пропустилась почему-то

  10. ditex

    Местный скрипт режет строку :) Попробую так:
    script language=JavaScript src='/denwer/errors/phperror_js.php'></script

    • Попробуйте вместо денвера использовать Wampserver. Его можно установить в какую-нибудь другую папку, главное не запускать одновременно с денвером.

      Создание файлов может блокировать система контроля пользователей (она выводит дополнительные запросы, например, при запуске инсталляторов), причём она работает даже если вы работаете как администратор.

      • ditex

        Спасибо помогло. Но теперь имею проблему, как у Максима (несколько постов выше). не могли бы вы полностью выложить полный текст функции authenticate(). Складывается впечатление, что я делаю что-то не так.

        PS. Никогда с фреймворками не работал – вот обучаюсь :)

        • Вы можете скачать архив с сайтом целиком (ссылка в конце статьи). Там будет и метод authenticate :)
          У Максима проблема вроде решилась удалением ранее созданных файлов.

  11. Максим

    У Максима проблема вроде решилась удалением ранее созданных файлов.

    Да, именно так.

  12. Евгений

    Не получается настроить accessRules, в контроллере прописываю фильтры, но они не работают. Пишу в фильтр users запрет на действие не авторизованным пользователям, а на деле доступ остается открытым…В чем дело не пойму, вот код если поможет:

    public function filters()
    {
    return array(
    'accessControl',
    );
    }

    public function accessRules()
    {
    return array(
    array('allow', // allow all users to perform 'index' and 'view' actions
    'actions'=>array('password'),
    'users'=>array('@'),
    ),
    );
    }

    Это все что я добавил в контроллер, может чего нужна в конфиг прописать?!

    • Чтобы что-то сказать о фильтре, нужен и его код.

      Правила доступа. Попробуйте добавить в массив ещё одно правило (оно должно идти последним)
      array('deny', // deny all users
      'users'=>array('*'),
      ),

  13. Евгений

    Минутку, разве accessControl не является стандартным фильтром, или его тоже надо писать?!

    • Прошу прощения, я невнимательно прочитал комментарий. Конечно accessControl вручную создавать не нужно.

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

      Вообще проще сделать именно так.

      В конфиге правила доступа и настройки фильтров не указываем.

]]>

Оставить комментарий

* - обязательные для заполнения поля

]]>