У меня есть блестящая идея. Я собираюсь создать сайт, который облегчает *insert verb*ing
для *insert noun*
. Хотя есть проблема: мне нужны люди, чтобы иметь возможность войти в систему, но я не хочу заниматься регистрацией пользователей, сбросом их паролей и т . Д. Поэтому я решил, что использование входа в Google — лучший вариант. Как я могу это реализовать?
С комбинацией Devise и Omniauth процесс не так болезнен, как кажется. По сути, я собираюсь использовать процесс, изложенный в спецификации OAuth 2.0, для реализации аутентификации для моего NounVerber.
Подтяните подтяжки
rails new
это хорошо, но мне нравится немного больше функциональности из коробки, поэтому я собираюсь использовать драгоценный камень Susbders от Thinkbot . Давайте создадим наше приложение:
$ gem install suspenders $ suspenders login_with_google # lots and lots of rails app creation output $ cd login_with_google
Во-первых, нам нужно создать несколько страниц для посещения:
-
home
— корневая страница, которая не защищена. -
secure
— только просмотр с логином.
Мы создадим контроллер pages
который имеет эти методы. Очевидно, это просто заполнитель, так как логин Google для статического контента будет несерьезным:
$ rails g controller pages home secure
Установите корневую страницу на pages#home
:
# config/routes.rb Rails.application.routes.draw do root to: 'pages#home' get 'pages/secure' end
Потрясающие. Но прежде чем мы начнем создавать аутентификацию, нам нужно создать модель User. Мы используем только API Google для аутентификации, поэтому нам понадобятся только следующие атрибуты:
-
uid
— уникальный идентификатор провайдера (Google) для нашего пользователя -
provider
— провайдер аутентификации -
name
— имя сохранено из их профиля Google -
email
— электронная почта, сохраненная из их профиля Google
Давайте сгенерируем эту модель:
$ rails g model user uid provider name email
Это должно создать нашу модель пользователя. Проверив миграцию, мы можем не беспокоиться о rake db:migrate
.
Примечание. Поскольку Suspenders пытается быть готовым к Heroku, для работы миграций на вашем компьютере должен быть установлен PostgreSQL. Если вы просто хотите использовать SQLite3, поменяйте местами конфигурацию базы данных и гемы.
Добавление Devise и Omniauth
Теперь, когда у нас есть страницы для отображения и пользователи правильно смоделированы в базе данных, пришло время для забавной части: добавление Devise и Omniauth.
Сначала добавьте драгоценные камни:
# Gemfile # ... gem 'devise' gem 'omniauth-google-oauth2' # ...
Драгоценный камень omniauth-google-oauth2 — это то, что делает магию. Теперь bundle install
и мы готовы к работе!
Чтобы это работало правильно, настройте несколько вещей:
- Установить Devise
- Настройте промежуточное программное обеспечение стойки
- Добавить Devise маршруты
- Добавить Devise к модели
User
- Создать контроллер обратных вызовов
- Добавить аутентификацию на защищенные страницы
Установка Devise
Devise предоставляет команду установки для легкой настройки:
$ rails g devise:install
Настройка промежуточного программного обеспечения Omniauth Rack
Нам нужно создать инициализатор промежуточного программного обеспечения omniauth для аутентификации нашего клиентского приложения в Google. Это делается с помощью идентификатора клиента и секрета:
# 'config/initializers/omniauth.rb' Rails.application.config.middleware.use OmniAuth::Builder do provider :google_oauth2, ENV["GOOGLE_CLIENT_ID"], ENV["GOOGLE_CLIENT_SECRET"] end
Вау, подожди минутку! Мы только что попросили учетные данные, которые еще не существуют? Да, мы сделали. Нам нужно, чтобы Google генерировал их для нас.
Сначала перейдите на https://console.developers.google.com/ и создайте проект. Затем, под «API & auth» на боковой панели, нажмите «Credentials», а затем нажмите «Create new Client ID». Теперь скопируйте и вставьте учетные данные, которые вы получите, в свой файл .env как GOOGLE_CLIENT_ID
и GOOGLE_CLIENT_SECRET
. Suspenders предоставляет гем dotenv, который позволяет нам помещать переменные среды в файл .env, который запускается Rails при запуске. Это хорошая практика, которая гарантирует, что мы не помещаем секреты в систему контроля версий.
Еще одна вещь, которая может сбить вас с толку позже — это включение API. Для нашей цели нам просто нужен Google+ API. Перейдите на страницу своего проекта в Google, нажмите «API» и включите Google+.
Добавление разработанных маршрутов
Devise создает метод devise_for
для создания пользовательских маршрутов для аутентификации, и нам нужно добавить маршруты для обработки потока OAuth:
# 'config/routes.rb' devise_for :users, controllers: { omniauth_callbacks: "users/omniauth_callbacks" }
Обратите внимание, что мы определили контроллер, который еще не существует. Мы вернемся к этому позже.
Добавление устройства в модель пользователя
У Devise есть еще один вспомогательный метод devise
, который настраивает нашу модель для использования функций Devise. Добавьте следующее в модель User
:
# 'app/models/user.rb' devise :omniauthable, omniauth_providers: [:google_oauth2]
Создание контроллера обратных вызовов
Когда пользователь входит в систему, он отправляется поставщику (в данном случае Google), а затем возвращается на исходный сайт по URL-адресу обратного вызова. Этот обратный вызов выполняет аутентификацию для пользователя на основе данных от провайдера. Давайте создадим этот обратный вызов:
# 'app/controllers/users/omniauth_callbacks_controller.rb' class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController def google_oauth2 @user = User.from_omniauth(request.env['omniauth.auth']) if @user.persisted? sign_in_and_redirect root_path, event: :authentication else redirect_to root_path, flash: { error: 'Authentication failed!' } end end end
Метод google_oauth2
в контроллере обратного вызова будет применяться только к маршруту: /users/auth/google_oauth2/callback
. Когда этот метод вызывается, он находит существующего пользователя или создает нового. Если пользователь существует или только что был создан, он вошел в систему и перенаправлен на корневой путь. В противном случае пользователь перенаправляется обратно в корень и мигает ошибка.
В более сложном приложении пути перенаправления, скорее всего, будут другими, но мы будем использовать корневую страницу для наших целей.
Подожди минуту! Мы вызвали метод с именем User.from_omniauth
, который не существует! Давайте перейдем к модели User и создадим ее. Этот метод примет хэш пользовательских аргументов и найдет или создаст нового пользователя:
# 'app/models/user.rb' ... def self.from_omniauth(auth) where(provider: auth[:provider], uid: auth[:uid]).first_or_create do |user| user.name = auth[:info][:name] user.email = auth[:info][:email] end end ...
Добавление аутентификации на защищенные страницы
Мы уже многое сделали, так что давайте сделаем это и проверим аутентификацию. Откройте браузер и перейдите по http://localhost:3000/users/auth/google_oauth2
и выполните шаги (вы знаете, что делать). Если это работает, вы будете перенаправлены на пустую страницу! Как здорово! Почти революционный! А если серьезно, то для обычного пользователя это выглядит так, как будто он абсолютно ничего не сделал.
Нам нужно добавить небольшой раздел информации для входа на нашу домашнюю страницу. Откройте приложение / view / home :
Скучно.
# 'app/views/pages/home.html.erb' <h1>Pages#home</h1> <p>Find me in app/views/pages/home.html.erb</p>
Захватывающе!
# 'app/views/pages/home.html.erb' <div class="container"> <% if user_signed_in? %> <p>Welcome back, <a href="mailto:<%= current_user.email %>"><%= current_user.name %></a>!</p> <% else %> <p><%= link_to 'Sign in.', user_omniauth_authorize_path('google_oauth2') %></p> <% end %> </div> <h1>Pages#home</h1> <p>Find me in app/views/pages/home.html.erb</p>
Теперь, если мы посетим домашнюю страницу, вот что мы получаем!
Теперь мы вошли в систему с Google! Трудная часть сделана.
Только авторизованный персонал
Помните, когда мы создавали наш контроллер страниц? Хорошо, эта secure
страница пригодится сейчас.
Сначала добавьте get 'pages/secure'
в config / rout.rb, а затем откройте контроллер страниц. Мы собираемся убедиться, что пользователь вошел в систему перед просмотром защищенной страницы.
# 'app/controllers/pages_controller.rb' class PagesController < ApplicationController def home end def secure unless user_signed_in? redirect_to root_path, flash: { error: 'Please sign in first.' } end end end
Если мы попытаемся перейти по http://localhost:3000/pages/secure
без входа в систему, мы вернемся на домашнюю страницу с мигающей ошибкой. И вот оно!
Вывод
Есть так много причин, почему вход в систему с Google является отличным выбором. Почти у каждого пользователя уже есть учетная запись Google, вам не нужно иметь дело со сменой имени пользователя / пароля, и вам не нужно беспокоиться о защите паролей, потому что у вас их нет. Благодаря процветающему сообществу Rails у нас есть инструменты для быстрой аутентификации в Google. Вместо страницы регистрации в вашем следующем проекте, почему бы вам не попробовать войти в систему с Google?
Весь пример кода проекта можно найти на GitHub .