За последний месяц я рассмотрел различные решения для аутентификации в Rails . Эта статья является пятой в серии (о мой), и наш гость сегодня — Распродажа.
Clearance — это продуманное решение для аутентификации и авторизации на основе электронной почты и паролей для Rails, созданное Thoughtbot Inc (ребята, которые создали FactoryGirl, PaperClip и другие классные библиотеки). Клиренс выполнен в виде двигателя Rails . Он предназначен быть маленьким, простым и хорошо проверенным. В некотором смысле, это похоже на Devise в том, что Clearance имеет много настроек по умолчанию, которые помогут вам начать работу почти через пять минут, и все эти настройки по умолчанию могут быть легко отменены. Однако, в отличие от Devise, в Clearance представлены только минимальные функциональные возможности, которые можно настраивать по своему усмотрению.
Это решение активно поддерживается, поэтому я очень рекомендую попробовать его. В этой статье я покажу, как интегрировать оформление, ограничивать доступ, настраивать его и использовать дополнительные проверки при входе в систему.
Исходный код можно найти на GitHub .
Рабочая демоверсия доступна по адресу sitepoint-clearance.herokuapp.com .
Препараты
Для начала создайте новое приложение Rails под кодовым названием «Чистое небо»:
$ rails new ClearSky -T
Для этой демонстрации будет использоваться Rails 4.2, но Clearance также совместим с Rails 3.2.
Если вы хотите следовать стилю приложения, добавьте следующий гем в ваш Gemfile, чтобы использовать стили Bootstrap:
Gemfile
[...] gem 'bootstrap-sass' [...]
Также измените файл application.scss :
таблицы стилей / application.scss
@import 'bootstrap-sprockets'; @import 'bootstrap';
Теперь обновите макет. Вам не нужно добавлять эти специфичные для Bootstrap блоки, но убедитесь, что флэш-сообщения отображаются где-то, потому что Clearance полагается на них для отображения важной информации для пользователя.
макеты / application.html.erb
[... <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <%= link_to 'Clear Sky', root_path, class: 'navbar-brand' %> </div> <div id="navbar"> </div> </div> </nav> <div class="container"> <% flash.each do |key, value| %> <div class="alert alert-<%= key %>"> <%= value %> </div> <% end %> <%= yield %> </div> [...]
Нам также понадобится базовая корневая страница, поэтому создайте контроллер страниц и соответствующий маршрут:
pages_controller.rb
class PagesController < ApplicationController def index end end
конфиг / routes.rb
[...] root to: 'pages#index' [...]
просмотров / страниц / index.html.erb
<div class="page-header"><h1>Welcome!</h1></div>
Теперь все готово, чтобы добавить оформление в наш проект. Перейдите к следующему шагу!
Интегрирующий зазор
Начать с оформления очень легко. Прежде всего, поместите драгоценный камень в свой Gemfile:
Gemfile
[...] gem 'clearance', '~> 1.11' [...]
Теперь запустите специальный генератор и примените миграции:
$ rails generate clearance:install $ rake db:migrate
Этот генератор делает следующее:
- Создает новый файл Clearance.rb в каталоге инициализаторов .
- Создает новую модель
User
, файл миграции и добавляет к ней строку «include Clearance::User
. Эта модель будет иметь следующие атрибуты:-
email
(string
) -
encrypted_password
(string
) -
confirmation_token
(string
) -
remember_token
(string
) - Основные атрибуты (
id
,created_at
,updated_at
)
-
- Добавляет
include Clearance::Controller
вApplicationController
. Таким образом, контроллеры будут иметь специальные методы очистки.
Если у вас уже есть модель User
, она будет соответствующим образом изменена. Если вы не хотите вызывать User
модели, измените настройку config.user_model
внутри файла инициализатора config.user_model
. В общем, этот файл — первое место для настройки настроек Clearance — полный список их см. В этом разделе в документации.
Обратите внимание на то, что, несмотря на то, что с параметром confirmation_token
есть, оно не используется Создание пользователя просто означает добавление новой записи в таблицу users
и запись этого пользователя в приложение. Таким образом, если вы хотите убедиться, что электронная почта подтверждена, прежде чем учетная запись будет использована, необходимо предпринять дополнительные шаги. В следующих разделах мы обсудим, как настроить оформление и выполнить дополнительные проверки входа в систему более подробно.
После запуска генератора Clearance в консоли будет напечатан небольшой список задач, поэтому убедитесь, что вы выполнили все необходимые шаги. Если вы подписаны, нужно выполнить только одно дополнительное действие:
конфигурации / среда / development.rb
[...] config.action_mailer.default_url_options = { host: 'localhost:3000' } [...]
Для производственной среды добавьте параметры, которые вам подходят.
Обратите внимание, что вы, вероятно, захотите изменить адрес электронной почты отправителя , а также:
конфиг / Инициализаторы / clearance.rb
[...] config.mailer_sender = '[email protected]' [...]
Очистка запущена и работает, поэтому мы можем добавить пункты меню «Вход» и «Выход»:
макеты / application.html.erb
[...] <div id="navbar"> <% if signed_in? %> <ul class="nav navbar-nav"> <li><%= link_to 'Add Page', new_page_path %></li> </ul> <% end %> <ul class="nav navbar-nav pull-right"> <% if signed_in? %> <li><span><%= current_user.email %></span></li> <li><%= link_to 'Sign out', sign_out_path, method: :delete %></li> <% else %> <li><%= link_to 'Sign in', sign_in_path %></li> <% end %> </ul> </div> [...]
signed_in?
и current_user
— вспомогательные методы, предоставляемые Clearance, которые довольно понятны. Вы также можете использовать signed_out?
метод.
sign_out_path
и sign_in_path
также создаются Clearance — мы обсудим их чуть подробнее в следующем разделе.
Ограничение доступа
Теперь, когда мы добавили базовую систему аутентификации, вы, вероятно, захотите ограничить доступ к некоторым страницам сайта. Это действительно легко сделать. Предположим, у нас есть new
действие внутри PagesController
:
pages_controller.rb
[...] def new end [...]
конфиг / routes.rb
[...] resources :pages, only: [:new] [...]
просмотров / страниц / new.html.erb
<div class="page-header"><h1>Add Page</h1></div>
Чтобы позволить только аутентифицированным пользователям получать доступ к этой странице, просто добавьте before_action
:
pages_controller.rb
before_action :require_login, only: [:new]
Теперь, если неаутентифицированный пользователь пытается получить доступ к этому маршруту, он будет перенаправлен на страницу «Вход». Чтобы изменить это поведение, переопределите метод url_after_denied_access_when_signed_out
в ApplicationController
и верните маршрут по вашему выбору. Узнайте больше здесь .
Оформление также обеспечивает ограничения маршрутизации, которые могут пригодиться. Например, если бы я хотел определить специальный корневой маршрут для всех аутентифицированных пользователей, я бы использовал следующие ограничения:
конфиг / routes.rb
[...] constraints Clearance::Constraints::SignedIn.new do root to: 'pages#new', as: :signed_in_root end constraints Clearance::Constraints::SignedOut.new do root to: 'pages#index' end [...]
Здесь все аутентифицированные пользователи будут иметь pages#new
в качестве корневой страницы. Для гостей pages#index
будет корнем. Обратите внимание, что если вы определите два корневых маршрута, один из них должен быть назван, в противном случае возникнет ошибка.
Настройка оформления
Вы, вероятно, задаетесь вопросом, как настроить Clearance дальше, например, как изменить представления, действия контроллеров или маршруты. Ну, это тоже довольно просто.
Начнем с маршрутов . Выполните следующую команду, чтобы скопировать маршруты по умолчанию в ваш файл rout.rb :
$ rails generate clearance:routes
Эта команда также установит для параметра config.routes
значение false
, что означает использование пользовательских маршрутов.
Внутри файлаways.rb вы увидите несколько новых строк кода:
конфиг / routes.rb
[...] resources :passwords, controller: "clearance/passwords", only: [:create, :new] resource :session, controller: "clearance/sessions", only: [:create] resources :users, controller: "clearance/users", only: [:create] do resource :password, controller: "clearance/passwords", only: [:create, :edit, :update] end get "/sign_in" => "clearance/sessions#new", as: "sign_in" delete "/sign_out" => "clearance/sessions#destroy", as: "sign_out" get "/sign_up" => "clearance/users#new", as: "sign_up" [...]
Не стесняйтесь изменять их по мере необходимости.
Чтобы переопределить методы контроллеров , создайте новый контроллер и сделайте его подкласс из одного из существующих: Clearance::PasswordsController
, Clearance::SessionsController
или Clearance::UsersController
. Теперь вы можете переопределять методы по своему усмотрению. Только не забудьте обновить маршруты, чтобы они указывали на ваш новый контроллер.
Изменение видов также просто. Бегать:
$ rails generate clearance:views
скопировать все виды по умолчанию в папку представлений и изменить их по своему усмотрению.
По умолчанию Clearance будет использовать макет вашего приложения, но это также можно изменить. Если вам необходимо создать пользовательский макет для одного из контроллеров, добавьте следующий код в файл инициализатора:
конфиг / Инициализаторы / clearance.rb
[...] Clearance::PasswordsController.layout 'my_passwords_layout' Clearance::SessionsController.layout 'my_sessions_layout' Clearance::UsersController.layout 'my_admin_layout' [...]
При копировании представлений по умолчанию с помощью команды, показанной выше, файл I18n также будет скопирован. Используйте его, чтобы изменить переводы по мере необходимости.
Модель пользователя по умолчанию имеет множество методов, которые также могут быть переопределены.
Дополнительные проверки входа
По умолчанию Clearance проверяет только электронную почту и пароль пользователя при аутентификации. Предположим, однако, что эта учетная запись приостановлена, и мы не хотим, чтобы эти пользователи могли войти. Это может быть реализовано с помощью так называемых «охранников входа» .
Прежде всего, добавьте новое поле в таблицу users
:
$ rails g migration add_suspended_to_users suspended:boolean
Изменить миграцию:
xxx_add_suspended_to_users.rb
class AddSuspendedToUsers < ActiveRecord::Migration def change add_column :users, :suspended, :boolean, default: false, index: true end end
и применить его:
$ rake db:migrate
Теперь откройте файл инициализатора и измените его следующим образом:
конфиг / Инициализаторы / clearance.rb
class SuspendedCheckGuard < Clearance::SignInGuard def call if suspended? failure("Your account is suspended.") else next_guard end end def suspended? current_user.suspended? end end Clearance.configure do |config| config.sign_in_guards = [SuspendedCheckGuard] [...] end
Не стесняйтесь извлекать SuspendedCheckGuard
в другой файл.
Идея, лежащая в основе SignInGuard
, довольно проста: он проверяет стек условий перед SignInGuard
пользователя.
Каждый охранник работает по порядку и передает сессию следующему охраннику в стеке.
SignInGuard
отвечает на метод call
. Он инициализируется сессией и текущим стеком. В случае успеха,
охранник должен вызвать следующего охранника или вернуть SuccessStatus.new
если вы не хотите, чтобы запускались последующие охранники. В случае неудачи охранник должен вызвать FailureStatus.new(failure_message)
.
Распродажа предоставляет базовый класс SignInGuard, который может быть унаследован. Этот класс уже реализует методы, такие как signed_in?
и current_user
.
В нашем примере мы определяем метод call
который проверяет, заблокирована ли учетная запись пользователя. Если да — установить сообщение об ошибке и запретить вход. Это сообщение будет отображаться во вспышке. Если нет — запустите следующую проверку, если она присутствует в стеке. Как только все проверки выполнены успешно, пользователь входит в систему.
Теперь вы можете загрузить свой сервер и проверить, как работает приложение!
Вывод
В этой статье мы обсудили Clearance — самоуверенную систему аутентификации и авторизации. Я рекомендую вам просмотреть вики проекта, так как в нем есть записи, объясняющие, как настраивать оформление в дальнейшем. Я думаю, что эта библиотека — отличная альтернатива Devise, если вам нужно быстро начать работу и не нужны все функции, которые предоставляет Devise.
Вы когда-нибудь использовали оформление? Рассматриваете ли вы использовать его в будущем? Поделитесь своим мнением!
Как всегда, я благодарю вас за то, что вы остались со мной и до скорой встречи!