Проекты: Аутентификация

Не забывайте использовать Git для фиксации изменений в ваших проектах!

Здесь вы создадите системы аутентификации, чтобы пользователи имели доступ только к тем разделам сайта, которые им разрешены.

Проект 1: Учебник Ruby on Rails

Изучение этого материала вы начнете с Учебника. Не торопитесь, выбирайте нужные файлы для внесения изменений (особенно это относится к спекам). Многие совершают досадную ошибку, помещая блок describe в неподходящее место.

Обеспечение возможности пользователю "входить" в приложение и "выходить" из него, станет первым этапом на пути создания прав редактирования, удаления (не забывайте, что не все функции стоит давать всем пользователям подряд, обычно данными правами обладают учетные записи администраторов и модераторов). Непосредственная реализация этих "опасных" операций будет происходить в 9-й главе Учебника.

Ваши задания

  1. Выполните Главу 8 Учебника, "Войти, выйти"
  2. Выполните Главу 9 Учебника, "Обновление, демонстрация и удаление пользователей"

Проект 2: Вход не для всех!

В этом проекте вы создадите "клуб для избранных", где его члены могут постить свои мнения о тех, кто не является его участником. При этом, авторство поста будет видно только внутри клуба, а находящиеся снаружи могут только гадать об авторе.

Вам предоставляется возможность "выкатить" свою собственную систему аутентификации, очень похожую на ту, которую вы создавали в Учебнике. Как обычно, мы сфокусируемся на данных и функциональности, но не красоте. Если же вы хотите "навести блеск", рассматривайте это как отдельное задание.

При создании своей системы аутентификации несложно запутаться. Причиной этому зависящие друг от друга контроллер/форма сессии, обновляющие при необходимости токен пользователя, который они используют для определения текущего пользователя. Если вы распишете шаги реализации до того, как начнете писать код, то это может помочь в понимании того, на что впоследствии вам будет необходимо обратить особое внимание.

Ваши задания

Наши проекты будут все менее подробны в плане их буквальной реализации, так как вы уже получили достаточный опыт. Если вы чего-то не знаете, просто вернитесь к предыдущим урокам или проектам, или же просто погуглите (здесь, правда, вы можете зайти гораздо глубже, чем ожидалось). Хорошим пособием будет наш Учебник по Ruby on Rails.

До сих пор мы рассматривали поле "password" достаточно легкомысленно... в общем мы включали его только для завершенности нашего приложения. Пароль не был ни сохранен, ни зашифрован, хотя должен был. Так что забудьте про такое отношение к паролю, потому что у вас теперь есть инструменты для должного шифрования пароля, и с этого момента мы будем ими пользоваться. На самом деле, эти инструменты имеются, начиная с тех пор, как вы закончили Главу 6 Учебника Ruby on Rails.

Если вы хотите испытать себя, то даже не читайте дальше, а просто попробуйте создать приложение!

Основная настройка

  1. Поразмышляйте о том, как настроить модели в приложении. Вам будут нужны пользователи с их обычными атрибутами (имя, e-mail, пароль), а также каким-то признаком принадлежности к клубному сообществу. Дайте им возможность создавать посты. И теперь вы будете использовать поле :password_digest вместо :password.
  2. Создайте новое приложение members-only и репозиторий Git. Обновите README.
  3. Начните с миграции и настройке модели User (пока без дополнительного атрибута).
  4. Добавьте гем bcrypt-ruby в ваш Gemfile. Выполните $ bundle install. (Примечание: это может быть просто bcrypt)
  5. Добавьте метод #has_secure_password в файл модели.
  6. Для проверки работоспособности, создайте пользователя из консоли Rails. Возможно, это будет выглядеть как-то так: User.create(:name => "foobar", :email => "foo@bar.com", :password => "foobar", :password_confirmation => "foobar")
  7. Проверьте из командной строки работу команды #authenticate, которая теперь нам доступна в модели (благодаря #has_secure_password) - вернет ли она пользователя, если вы укажете верный пароль?

        > user = User.create(:name => "foobar", :email => "foo@bar.com", :password => "foobar", :password_confirmation => "foobar")
        > user.authenticate("somethingelse")
        => false
        > user.authenticate("foobar")
        => true
    

Сессии и вход в систему

Теперь проверим, смогут ли пользователи войти.

  1. Создайте контроллер sessions_controller.rb и соответствующие маршруты. Создайте в макете необходимые ссылки "sign in".
  2. В действии #new создайте пустую сессию и отошлите ее вьюхе.
  3. Создайте простую форму с #form_for, чтобы пользователь логинился на app/views/sessions/new.html.erb. Проверьте, что вы можете ее видеть.
  4. Нам необходимо помнить о том, что пользователь залогинен, поэтому необходимо создать столбец в таблице User и назвать его, например, :remember_token. В нем будет храниться токен (ключ сессии) пользователя.
  5. При создании нового пользователя, ему необходимо дать новый токен. Используйте колбэк #before_create в модели User для:

    1. Создания токена (используйте SecureRandom.urlsafe_base64 для генерации случайной строки)
    2. Зашифруйте этот токен (с помощью метода Digest::SHA1.hexdigest на строке (#to_s) токена)
    3. Сохраните его для пользователя.
  6. Создайте пару пользователей в своем приложении. Мы не будем создавать форму регистрации пользователей, так что придется использовать командную строку. Метод #before_create теперь должен создавать токен каждому новому пользователю.

  7. Теперь в действии #create контроллера SessionsController необходимо создать пользовательскую сессию. Сначала необходимо найти пользователя по его e-mail, а затем сравнить хэш введенного им пароля из 'params' с хэшированным паролем в базе данных, используя #authenticate. Посмотрите Главу 8 если возникнут вопросы с этим, но только для ознакомления. Не переносите ничего отсюда в код.

  8. Как только вы проверили, что пароль пользователем указан верный, он залогинивается.

  9. Создайте новый метод в контроллере ApplicationController, который выполняет эту процедуру. Предоставьте пользователю новый токен (во избежание его кражи или устаревания). Сохраните его в пользовательском браузере с помощью куки, чтобы при переходе по страницам мы могли проверять, залогинен ли пользователь. Сделайте это, используя cookies.permanent.

  10. в контроллере ApplicationController создайте два других метода - один для получения текущего пользователя (#current_user), другой для его установки (#current_user=(user)). Для получения текущего пользователя используйте оператор ||= - если он уже существует, то возвращаем его, иначе следует получить текущий токен из куки и поискать по нему подходящего пользователя. Если поиск ничего не дал, возвращаем nil.

  11. Установите текущего пользователя в момент логина.

  12. Создайте функционал выхода из системы в действии SessionsController#delete, который удаляет текущего пользователя и удаляет токен из куки. Лучшим способом будет вызов метода (например #sign_out) в контроллере ApplicationController вместо того, чтобы расписывать все в SessionsController.

  13. Создайте ссылку для выхода, указывающую на метод #delete в контроллере сессий. Необходимо будет имитировать метод HTTP DELETE, и это легко реализуется добавлением опции :method => :delete к #link_to.

Аутентификация и Посты

Let's build those secrets! We'll need to make sure only signed in users can see the author of each post. We're not going to worry about editing or deleting posts.

  1. Создайте модель Post, контроллер и соответствующий ресурс в файле маршрутов, который будет принимать методы [:new, :create, :index].
  2. В контроллере используйте #before_filter для ограничения доступа незалогиненных пользователей к методам #new и #create. Создайте необходимые методы-помощники в ApplicationController.
  3. Создайте действие #new в PostsController.
  4. Создайте несложную форму в app/views/posts/new.html.erb, для нового поста.
  5. Действие #create должно создавать пост с внешним ключом автора (например user_id), которое берется из текущего залогиненного пользователя. После успешного создания поста, сделайте перенаправление на вьюху Index.
  6. Внесите необходимые изменения в действие #index и создайте соответствующую вьюху. Она должна отображать список всех постов.
  7. Добавьте логику во вьюху Index для отображения имени автора только залогиненным пользователям.
  8. Залогиньтесь и создайте несколько секретных постов.
  9. Проверьте - разлогиньтесь и перейдите на индексную страницу. Вы должны увидеть список постов, но не их авторов. Залогиньтесь снова и имена авторов должны появиться. Ваши тайны в безопасности!

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

Решения студентов

Дополнительные ресурсы

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

*

Поделиться уроком: