Настройка Devise и OmniAuth для обслуживания Rails-приложения

Для корректной работы большинства приложений Ruby on Rails необходимы механизмы аутентификации. Такой механизм можно разработать самостоятельно или использовать для этого специальный gem по имени Devise, позволяющий создавать полноценные системы аутентификации пользователей в течение нескольких минут.

Кроме того, можно позволить пользователям получить доступ к приложению при помощи уже существующей учётной записи (например, аккаунта Facebook, Twitter и т.п.). Тогда им не придётся создавать новую учетную запись для доступа к приложению. Настроить такую аутентификацию можно при помощи любого популярного сервиса OAuth. Поддержка OAuth для приложений Ruby on Rails обеспечивается gem-ом OmniAuth.

Это руководство поможет создать приложение при помощи gem-ов Devise и OmniAuth.

Требования

Для работы понадобятся последние версии RVM, Ruby и Rails. Полезные инструкции по установке и обновлению этих программ можно найти в специальном разделе нашего Информатория.

Примечание: В данном руководстве используются версии Ruby 2.1.2 и Rails 4.1.5.

1: Создание Rails-приложения

Приложения Rails рекомендуется хранить в отдельном каталоге.

Создайте такой каталог:

mkdir rails_apps
cd rails_apps

Инициируйте окружение RVM, прежде чем начать использовать команды Rails.

. ~/.rvm/scripts/rvm
rvm use ruby --default

Примечание: Это нужно делать каждый раз при перезагрузке терминальной сессии.

В данном руководстве новое приложение будет условно называться myapp. Создайте приложение и перейдите в его каталог:

rails new myapp
cd myapp

Примечание: Все команды Rails нужно запускать в каталоге приложения (в данном случае это ~/rails_apps/myapp).

2: Добавление gem-ов

Теперь нужно добавить gem-ы Devise и OmniAuth. Кроме того, вам понадобятся отдельные gem-ы для поддержки каждого отдельного сервиса OAuth; к примеру, для аутентификации при помощи Facebook нужен gem omniauth-facebook.

Добавьте следующий код в ~/rails_apps/myapp/Gemfile.

gem 'therubyracer'
gem 'devise'
gem 'omniauth'
gem 'omniauth-facebook'

Для поддержки аутентификации при помощи других сервисов нужны дополнительные gem-ы:

  • Twitter – omniauth-twitter
  • Amazon – omniauth-amazon
  • Google – omniauth-google
  • Github – omniauth-github

При необходимости добавьте их в Gemfile.

Чтобы установить эти gem-ы, введите:

bundle install

3: Функции приложения

Теперь нужно добавить несколько тестовых страниц приложения, которые будут доступны только после аутентификации.

Для этого можно использовать функцию Rails под названием scaffolding. При помощи команды rails g scaffold можно просто задать параметры модели, и Rails самостоятельно соберёт полноценные страницы  для операций CRUD (Create Read Update Delete). Другими словами, вместе с моделью Rails создаст контроллер и вид.

rails g scaffold Product name:string price:integer description:text

После этого нужно определить root-каталог приложения.

Отредактируйте файл ~/rails_apps/myapp/config/routes.rb и укажите root приложения под строкой resources. Все закомментированные строки можно проигнорировать.

Rails.application.routes.draw do
resources :products
root 'products#index'
end

После этого можно протестировать приложение. Запустите сервер разработки:

rails s

Посетите http://localhost:3000/ в браузере. Если вы ведёте удалённую разработку, замените localhost IP-адресом сервера. 3000 – это стандартный порт сервера разработки.

На данный момент приложение не требует аутентификации.

При помощи New Product добавьте немного контента. Чтобы остановить сервер  разработки и вернуться в терминал, нажмите Ctrl+C.

4: Настройка Devise

Введите следующие команды, чтобы добавить поддержку авторизации Devise.

rails generate devise:install
rails generate devise User
rake db:migrate

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

Теперь приложение имеет базовую систему аутентификации, при помощи которой пользователи могут регистрироваться и получать доступ к контенту. Однако все страницы приложения всё ещё доступны без аутентификации. Чтобы изменить это, отредактируйте файл ~/rails_apps/myapp/app/controllers/application_controller.rb и добавьте действие authenticate_user!.

class ApplicationController < ActionController::Base
protect_from_forgery with: :exception
before_action :authenticate_user!
end

Теперь можно снова запустить сервер разработки:

rails s

и посетить http://localhost:3000/ (при необходимости замените localhost IP-адресом сервера). На экране появится форма входа.

Чтобы зарегистрировать нового пользователя, откройте ссылку:

http://localhost:3000/users/sign_up

5: Поддержка OmniAuth

Остановите сервер разработки (CTRL-C) и добавьте в модель Devise новый столбец, uid.

rails g migration AddColumnsToUsers provider uid
rake db:migrate

6: Настройка сервиса OAuth

Посетите сайт сервиса OAuth и зарегистрируйте на нём свое приложение (к примеру, чтобы настроить поддержку аутентификации при помощи Facebook, нужно предварительно зарегистрировать приложение в Facebook). Процедура регистрации отличается в зависимости от сервиса. В процессе регистрации будет запрошен URL обратного вызова:

  • Facebook: http://localhost:3000/users/auth/facebook/callback
  • Amazon: http://localhost:3000/users/auth/amazon/callback
  • Twitter: http://localhost:3000/users/auth/twitter/callback
  • Google: http://localhost:3000/users/auth/google/callback

Примечание: При необходимости замените localhost IP-адресом сервера.

После регистрации программа предоставит с клиентские данные (ID и secret), которые понадобятся на следующем этапе настройки.

7: Обновление инициализатора Devise

Отредактируйте ~/rails_apps/myapp/config/initializers/devise.rb и добавьте в конец файла ID и secret клиента (перед строкой end). Также рекомендуется обновить mailer_sender, указав имя пользователя или сервера.

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

Devise.setup do |config|
#Replace example.com with your own domain name
config.mailer_sender = 'mailer@example.com'
require 'devise/orm/active_record'
config.case_insensitive_keys = [ :email ] config.strip_whitespace_keys = [ :email ] config.skip_session_storage = [:http_auth] config.stretches = Rails.env.test? ? 1 : 10
config.reconfirmable = true
config.expire_all_remember_me_on_sign_out = true
config.password_length = 8..128
config.reset_password_within = 6.hours
config.sign_out_via = :delete
#Add your ID and secret here
#ID first, secret second
config.omniauth :facebook, "db381dc9990be7e3bc42503d0", "5b0824c2722b65d29965f1a1df"
end

8: Обновление модели User

Сгенерированная Devise модель User должна содержать данные о сервисе. Добавьте в код следующие элементы:

:omniauthable,
:omniauth_providers => [:facebook]

(не забудьте поставить запятую). Также нужно создать новый метод from_omniauth, который будет извлекать данные, доступные после аутентификации.

После редактирования файл ~/rails_apps/myapp/app/models/user.rb будет иметь следующий вид:

class User < ActiveRecord::Base
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable,
:omniauthable, :omniauth_providers => [:facebook] def self.from_omniauth(auth)
where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
user.provider = auth.provider
user.uid = auth.uid
user.email = auth.info.email
user.password = Devise.friendly_token[0,20] end
end
end

Сохраните и закройте файл.

9: Добавление контроллера

Сначала отредактируйте ~/rails_apps/myapp/config/routes.rb и укажите в строке devise_for имя контроллера, который будет обрабатывать обратные вызовы. Для примера можно назвать его просто callbacks. Теперь файл должен выглядеть так (без учёта комментариев):

Rails.application.routes.draw do
devise_for :users, :controllers => { :omniauth_callbacks => "callbacks" }
resources :products
root 'products#index'
end

Затем нужно создать новый файл, ~/rails_apps/myapp/app/controllers/callbacks_controller.rb, и добавить в него такой код:

class CallbacksController < Devise::OmniauthCallbacksController
def facebook
@user = User.from_omniauth(request.env["omniauth.auth"])
sign_in_and_redirect @user
end
end

Чтобы настроить больше сервисов OAuth, нужно добавить метод для каждого из них. Имя метода должно совпадать с именем сервиса.

Приложение готово. Снова запустите сервис:

rails s

Посетите домашнюю страницу. На странице должна появиться ссылка Sign in with Facebook. Кликните по ссылке, и на экране появится форма входа Facebook. Введите свои учётные данные, после чего вы будете перенаправлены к защищённому контенту приложения.

Заключение

Теперь приложение имеет продвинутую систему аутентификации, которая позволяет регистрироваться при помощи почтового адреса учётной записи социальных сетей и т.п.

Tags: , , ,

1 комментарий

  • Максим says:

    Указанная инструкция приводит к ошибке:
    “SQLite3::ConstraintException: NOT NULL constraint failed: users.email: INSERT INTO “users” (“email”, “encrypted_password”, “sign_in_count”, “current_sign_in_at”, “last_sign_in_at”, “current_sign_in_ip”, “last_sign_in_ip”, “created_at”, “updated_at”, “provider”, “uid”) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)”

Добавить комментарий для Максим Отменить ответ