Розбираємо модуль Auth, Вивчаємо Web
Давно не писав про Kohana 2.3.x. Захопившись третьою версією, закинув (сподіваюся, тимчасово) написання форуму як частиниCMS, загалом соромно стало. Вирішив розібрати по кісточках напевно найпопулярніший модуль з дистрибутива, мова піде звичайно ж про модуліAuth.
Що всередині?
Завітайте до директорії MODPATH/auth:
Конфігурація
Конфігураційний файл config/auth.php містить нечисленні налаштування модуля:
КласAuth, як вже було сказано раніше, дозволяє працювати з різними способами зберігання та обробки даних, для цього використовуються драйвери. Однак наявний драйвер на основі файлів має дуже обмежені можливості (практично тільки login/logout), дані про користувачів складаються лише їх логіна та пароля, зберігаються в текстових файлах (точніше у згаданому раніше $config['users']) і підвантажуються відразу. Тому зазвичай вони у документації не фігурують. А осьORM -драйвер набагато продуктивніший, так що надалі розглядатимемо тільки його використання.
Розглянемо основні можливості бібліотекиAuth на прикладі типових дій користувача. Оскільки зазвичай робота з користувачами проводиться у всіх контролерах проекту, зручно в базовому контролері зберігати екземпляр об'єктаAuth, щоб надалі використовувати його як властивість (property) контролера, наприклад:
Передмова. Хеші, солі та інші прянощі
Заходу на сайт звичайно повинна передувати реєстрація. А після реєстрації користувача необхідно зберегти пароль, але не в явному вигляді! Тому використовуються різні алгоритми хешування. УKohana використовується шифрування із застосуванням «солі», що збільшує складність розшифрування пароля, що зберігається.Давайте розглянемо такий код:
Даний приклад у результаті виведе щось на кшталт 'e8dabc6b7e1fb46b08d591c66dde7fb783a1dbe4' 'c66692385b1c5aaefef96fc9d94f4a56ee72753
Якщо ви кілька разів оновите сторінку, то стане помітно, що перший рядок не змінюється, а другий щоразу різний. Справа в тому, що в першій виводиться результат простого хешування введеного пароля (методhash($password) ), він більше ні від чого не залежить. У другому випадку ми застосовуємо хешування з «сіллю», внаслідок чого хеш стає зовсім іншим.
Отже, це у методіhash_password($password, $salt = FALSE). Перший параметр ясний – це пароль у початковому вигляді (нешифрований). Другий параметр — рядок із «солоними» символами. Після реєстрації цей метод викликається без параметра $salt і сіль генерується автоматично (береться хеш від випадкового GUID і обрізається до кількості елементів у параметрі $config['salt_pattern']). Далі найцікавіше - сіль вставляється в рядок з паролем як префікс (тобто виходить $salt.$password) і все це відправляється в методhash(). Отриманий у результаті хеш додатково розбавляється символами «солі» у місцях, вказаних параметром $config['salt_pattern'] (наприклад, якщо в патерні першим елементом йде одиниця, після першого символу пароля буде вставлено один символ «солі»).
Зрозуміло? Якщо так, то ви, напевно, помилилися сайтом. Найпростіше розглянути приклад, що показує етапи обчислення хешу:
На виході отримаємо такі рядки: e8dabc6b7e1fb46b08d591c66dde7fb783a1dbe4 8104ba1dc0 0171bfa8e8a0450af6972cc61c6c80408 045b0aaf69712dcc61c6cc200407a65bf47 На першу можете особливо не звертати увагу, вона простопоказує, наскільки далекий звичайний хеш пароля отриманого із застосуванням «солі». Другий рядок — це хеш «солі», що використовується, з нього беруться символи для вставки в хеш пароля. Наприклад, перший символ (цифра вісім) буде вставлено після першого символу пароля (вказано в salt_pattern). Третій рядок - це практично підсумковий хеш, але до вставки елементів "солі". Він відрізняється від хеша просто пароля, т.к. на початок рядка була вставлена змінна $hashed_salt. Ну, а між третім і четвертим рядком навіть видно схожість. Підсумковий хеш «розбух» ще на 10 символів (стільки елементів у salt_pattern), місця вставки «крупиць солі» ви легко побачите. Сподіваюся, що тепер стало зрозуміліше.
Сподіваюся, ви розумієте, що з різною "сіллю". вийдуть різні хеші. Більш того, важливий не тільки сам рядок із «сіллю», а й параметр $config['salt_pattern'].
Ще одна передмова. Ролі
Ролі та користувачі між собою взаємодіють за допомогоюORM -моделей Auth_User та Auth_Role. Так як у кожного користувача може бути кілька ролей, і роль може бути призначена різним користувачам, зв'язок між ними «багатьом» (has_and_belongs_to_many). Нагадаю, що для роботи з таким видом зв'язків уORM використовуються методиhas(),add() таremove().
Ролі вAuth підтримують методunique_id($id), тому можна використовувати конструкції виду ORM::factory('role', 'login');
Користувач вводить свої логін та пароль, які передаються формою для обробки контролером. Для перевірки коректності введених даних існує методlogin($username, $password, $remember = FALSE). Перші два параметри зрозумілі, третій — та сама галочка для автоматичного входу надалі. У нашому контролері перевірка відбуватиметься приблизнотак:
А що відбувається всередині методуlogin() ? Давайте заглянемо.
Порожні паролі не підтримуються взагалі (метод одразу повертаєFALSE ). Далі необхідно порівняти паролі. Так як у БД пароль зберігається в захешованому вигляді, треба порівнювати хеші паролів. Як вже було сказано вище, якщо не знати «сіль», використану при першому хешуванні, другий хеш того ж пароля вийде зовсім іншим. Тому для отримання «солі» з готового хешу використовується методfind_salt($password). Він використовує вказаний у конфігурації шаблон (salt_pattern) і висмикує з хеша символи, що зберігається.
Далі все просто – порівнюємо отриманий хеш зі старим та видаємо вердикт. Як бонус різні драйвери можуть виконувати додаткові дії у випадку, якщо логін успішний. Наприклад, драйверORM додатково перевіряє, чи є у користувача права на логін (для цього передбаченіролі ), чи потрібно запам'ятати даного користувача, збільшує лічильник входів та зберігає час останнього логіну. Крім того, в сесії (під ім'ям, вказаним у config['session_key']) зберігається об'єкт із даними користувача (для драйвераORM це об'єкт класуUser_Model ).
Звичайно, змушувати користувача вводити логін та пароль на кожній сторінці безглуздо. МодульAuth дозволяє перевіряти, чи увійшов на сайт користувач або він ще поки що гість. Для цього є «висить» у сесії об'єктUser_Model і методlogged_in().
Методget_user() повертає об'єктUser_Model із сесії, якщо він там є. ІнакшеFALSE.
Для виходу з сайту використовується методlogout($destroy = FALSE), який знищує об'єктUser_Model із сесії, а також може і зруйнувати саму сесію (якщо параметр $destroyвстановлений уTRUE ). У принципі, достатньо викликуlogout() без параметрів. Метод повертаєTRUE /FALSE, залежно від успішного видалення об'єкта із сесії.
Додаткові відомості про token:
Якщо ви хочете використовувати можливість автовходу, відразу після перевірки методомlogged_in() додайте виклик методуauto_login() :