Статьи

Разработать аутентификацию в глубину

deviselogo

Это вторая статья в серии «Аутентификация с помощью Rails». Мы собираемся обсудить Devise , популярное, полноценное решение для аутентификации от Platformatec .

По сравнению с Sorcery (который я посмотрел в прошлый раз ), Devise — это решение более высокого уровня, которое заботится о многих аспектах для вас. Он представляет контроллеры, представления, почтовые программы и маршруты. Несмотря на то, что просто выпустить пару команд и запустить Devise, они очень настраиваемы. У Devise есть очень полная документация и большое сообщество, которое производит множество полезных расширений. Неудивительно, что Devise так популярен.

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

В этой статье я расскажу:

  • Интеграция Devise в демонстрационное приложение
  • Настройка Devise и включение определенных модулей
  • Настройка Devise
  • Ограничение доступа к определенным страницам
  • Настройка асинхронной доставки электронной почты
  • Интеграция расширения Devise для оценки надежности пароля
  • Добавление оценки надежности пароля на стороне клиента

Звучит хорошо? Давайте начнем!

Демо-версия приложения находится по адресу https://sitepoint-devise.herokuapp.com/.
Исходный код находится на Github .

Земляные работы

Как и в предыдущей статье серии, мы собираемся создать приложение, которое не предоставляет никакой функциональности, кроме
от аутентификации (с некоторыми связанными функциями). На этот раз я не мог придумать ни одного причудливого имени, поэтому я назвал его просто «Разработать демо»:

$ rails new DeviseDemo -T 

Rails 4.2.0 используется, но Devise также совместим с Rails 3.

Загляните в некоторые драгоценные камни:

Gemfile

 [...] gem 'devise', '3.4.1' gem 'bootstrap-sass' [...] 

bootstrap-sass не имеет отношения к уроку, но он мне нравится для стилизации.

Следующий прогон

 $ bundle install 

Подключите стили Bootstrap:

application.scss

 @import "bootstrap-sprockets"; @import "bootstrap"; @import 'bootstrap/theme'; 

и изменить макет:

просмотров / макеты / application.html.erb

 [...] <div class="container"> <% flash.each do |key, value| %> <div class="alert alert-<%= key %>"> <%= value %> </div> <% end %> </div> <%= yield :top_content %> <div class="container"> <h1><%= yield :header %></h1> <%= yield %> </div> [...] 

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

Как вы можете видеть, я использую yield здесь, чтобы разместить дополнительный контент, называемый top-content и header . Кроме того, я добавил этот вспомогательный метод для предоставления заголовка:

application_helper.rb

 [...] def header(text) content_for(:header) { text.to_s } end [...] 

Давайте также настроим нашу домашнюю страницу. Создать PagesController

pages_controller.rb

 class PagesController < ApplicationController end 

Тогда мнение:

просмотров / страниц / index.html.erb

 <% content_for :top_content do %> <div class="jumbotron"> <div class="container"> <h1>Welcome!</h1> <p>Register to get started.</p> <p> <%= link_to 'Register', new_user_registration_path, class: 'btn btn-primary btn-lg' %> </p> </div> </div> <% end %> 

и маршрут, чтобы связать это вместе:

конфиг / routes.rb

 [...] root to: 'pages#index' [...] 

Наконец, настройте параметры URL по умолчанию для разработки:

конфигурации / среда / development.rb

 [...] config.action_mailer.default_url_options = { host: '127.0.0.1', port: 3000 } [...] 

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

Гениально, теперь пришло время интегрировать Devise!

Интеграция Devise

Прежде всего, запустите следующую команду, чтобы сгенерировать файл конфигурации Devise и переводы:

 $ rails generate devise:install 

config / initializers / devise.rb содержит множество различных параметров конфигурации, которые хорошо документированы. Мы настроим этот файл через минуту. config / locales / devise.en.yml представляет специфичные для Devise переводы на английский. Есть много переводов для других языков, которые можно найти здесь .

Затем сгенерируйте модель с дополнительными столбцами, которые требуются Devise:

 $ rails generate devise User 

Вы можете заменить User любым другим именем. Эта команда собирается создать файл модели user.rb и миграцию, которая добавляет все необходимые поля. Если модель User уже существует, она будет обновлена.

Откройте файл модели, чтобы увидеть, что он содержит. Наиболее важная строка:

модели / user.rb

 [...] devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable [...] 

Это список модулей Devise, которые активны для этой модели.

  • database_authenticatable — пользователи смогут проходить аутентификацию с помощью логина и пароля, которые хранятся в базе данных. (пароль хранится в виде дайджеста ).
  • registerable — пользователи смогут регистрировать, обновлять и уничтожать свои профили.
  • recoverable — предоставляет механизм сброса забытых паролей.
  • rememberable Память» — включает функцию «запомни меня», которая включает куки
  • trackable — отслеживает вход в счетчик, временные метки и IP-адрес.
  • validatable — проверяет электронную почту и пароль (могут использоваться пользовательские валидаторы).

Видеть? Devise позаботится о многих аспектах для вас — просто выберите нужные модули!

Для этой демонстрации давайте также используем два дополнительных модуля:

  • confirmable — пользователи должны будут подтвердить свои электронные письма после регистрации, прежде чем им будет позволено войти в систему.
  • lockable — учетные записи пользователей будут заблокированы после нескольких неудачных попыток аутентификации.

Измените модель следующим образом:

user.rb

 [...] devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable [...] 

Вы также должны отредактировать файл миграции, поэтому откройте его и раскомментируйте следующие строки:

дб / Миграция / xxx_devise_create_users.rb

 [...] t.string :confirmation_token t.datetime :confirmed_at t.datetime :confirmation_sent_at t.string :unconfirmed_email t.integer :failed_attempts, default: 0, null: false t.string :unlock_token t.datetime :locked_at add_index :users, :confirmation_token, unique: true add_index :users, :unlock_token, unique: true [...] 

Эти поля обязательны для правильной работы модулей Confirmable и Lockable. Также неплохо разрешить пользователям указывать свое имя, поэтому добавьте еще одну строку:

дб / Миграция / xxx_devise_create_users.rb

 [...] t.string :name [...] 

Теперь запустите миграцию:

 $ rake db:migrate 

Таблица пользователей теперь создана, и Devise запущен и работает. Однако нам еще есть чем заняться.

Настройка Devise

Как упоминалось ранее, настройки Devise присутствуют в файле инициализатора devise.rb . Откройте его и найдите раздел «Конфигурация для: блокируемого». Большинство настроек здесь будут закомментированы, поэтому раскомментируйте их и предоставьте следующие значения:

  • config.lock_strategy = :failed_attempts — это означает, что учетная запись будет заблокирована после нескольких неудачных попыток входа в систему. На самом деле, это единственная доступная стратегия, но вы можете установить для этого параметра значение none и самостоятельно управлять механизмом блокировки.
  • config.unlock_strategy = :both — учетную запись можно разблокировать либо по электронной почте (путем посещения ссылки, указанной в электронном письме, отправленном Devise), либо просто подождав некоторое время. Укажите :email или :time чтобы включить только один из этих двух вариантов. Обеспечить :none чтобы справиться с процессом разблокировки самостоятельно
  • config.maximum_attempts = 20 — количество раз подряд пользователь может ввести неверный пароль, прежде чем учетная запись заблокирована.
  • config.unlock_in = 1.hour — как долго аккаунт будет разблокирован. Укажите этот параметр, только если вы используете стратегию разблокировки :time или :both .
  • config.last_attempt_warning = true — выдает предупреждение, когда пользователю остается одна попытка входа в систему. Это предупреждение будет отображаться в виде мгновенного сообщения.

Отлично, теперь ищите раздел «Конфигурация для: подтверждаемого» и раскомментируйте следующие параметры:

  • config.confirm_within = 3.days — сколько времени пользователь должен активировать учетную запись по ссылке, отправленной по электронной почте (в основном это означает, что сгенерированный Devise токен активации больше не будет действительным). Если учетная запись не была активирована, можно запросить новый токен. Установите значение nil если вы не хотите, чтобы срок действия маркера активации истек.
  • config.reconfirmable = true — Если пользователь повторно подтверждает электронное письмо, когда оно изменяется с помощью обновления профиля. Этот процесс аналогичен процессу подтверждения после регистрации. Это новое неподтвержденное электронное письмо хранится в поле unconfirmed_email до тех пор, пока пользователь не перейдет по ссылке активации. В этот период старая электронная почта используется для входа в систему.

Если вы создаете настоящее приложение, также не забудьте настроить эти параметры:

  • config.mailer_senderconfig.mailer_sender адрес электронной почты, который будет помещен в поле «От».
  • config.secret_key — Секретный ключ для генерации различных токенов. Изменение этого параметра сделает все ранее сгенерированные токены недействительными.

В этом файле есть еще много настроек, которые вы можете изменить. Например, config.password_length который устанавливает минимальную и максимальную длину пароля (по умолчанию это 8..128 ).

Настройка Devise

Генерация просмотров

Хорошо, теперь Devise настроен так, как нам нравится. Загрузите сервер, перейдите на главную страницу и нажмите ссылку «Зарегистрироваться». Вам будет представлена ​​основная форма, но есть две вещи, на которые следует обратить внимание:

  • Эта форма не позволяет вам указывать имя, даже если мы добавили его при переносе.
  • Если вы используете Bootstrap для стилизации, форма будет выглядеть не очень хорошо (хорошо, это не такая уж большая проблема, но давайте все же примем это во внимание).

К счастью, есть способ настроить все представления, предоставляемые Devise. Бегать

 $ rails generate devise:views 

скопировать стандартные виды Devise непосредственно в папку вашего приложения. Новая папка с именем devise будет создана внутри каталога views . Позвольте мне кратко провести вас через все папки, которые находятся внутри:

  • Подтверждения — это единственное представление new.html.erb , которое отображается, когда пользователь запрашивает повторную отправку подтверждения по электронной почте.
  • mailer — все шаблоны для писем хранятся здесь.
  • пароли — представления с формами для запроса пароля, сброса электронной почты и фактического изменения пароля.
  • регистрации — представление new.html.erb отображается, когда пользователь регистрируется на сайте. edit.html.erb содержит форму для обновления профиля.
  • сессий — есть только один вид, который является формой входа на сайт.
  • общий доступ — здесь присутствует только один фрагмент, который содержит ссылки, которые отображаются на каждой странице Devise (например, «Забыли пароль?», «Повторно отправить электронное письмо с подтверждением» и т. д.)
  • Разблокировка — только один вид с формой для запроса электронной почты со ссылкой для разблокировки.

Если вы хотите настроить представления только для определенных модулей (например, registerable и confirmable ), выполните эту команду:

 $ rails generate devise:views -v registrations confirmations 

Вы даже можете иметь отдельные представления для разных моделей (если в вашем приложении несколько моделей, которые оснащены Devise):

 $ rails generate devise:views users 

Узнайте больше здесь .

Форма регистрации

А сейчас давайте просто изменим представление, предоставляющее форму регистрации, добавив еще одно поле и стилизовав его:

просмотров / Завещание / регистрация / new.html.erb

 <% header "Sign Up" %> <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> <div class="form-group"> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :email %> <%= f.email_field :email, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :password %> <%= f.password_field :password, autocomplete: "off", class: 'form-control' %> <% if @validatable %> <span class="help-block"><%= @minimum_password_length %> characters minimum</span> <% end %> </div> <div class="form-group"> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control' %> </div> <%= f.submit "Sign up", class: 'btn btn-primary' %> <% end %> <%= render "devise/shared/links" %> 

header — наш вспомогательный метод для отображения заголовка страницы. devise_error_messages! отображает любые ошибки, которые были обнаружены при попытке сохранить запись.

Перезагрузите сервер и зарегистрируйте нового пользователя. Теперь вы сможете указать свое имя.

Главное меню и флеш-сообщения

После перенаправления обратно на главную страницу вы заметите еще несколько проблем:

  • Нет способа определить, какой пользователь вошел в систему.
  • Нет возможности выйти из системы.
  • Приветственное флэш-сообщение не оформлено правильно (если вы придерживаетесь Bootstrap).

Первые две проблемы легко решаются добавлением главного меню следующим образом:

просмотров / макеты / application.html.erb

 <nav class="navbar navbar-inverse"> <div class="container"> <div class="navbar-header"> <%= link_to 'Devise Demo', root_path, class: 'navbar-brand' %> </div> <div id="navbar"> <ul class="nav navbar-nav"> <li><%= link_to 'Home', root_path %></li> </ul> <ul class="nav navbar-nav pull-right"> <% if user_signed_in? %> <li class="dropdown"> <a class="dropdown-toggle" data-toggle="dropdown" href="#"> <%= current_user.name %> <span class="caret"></span> </a> <ul class="dropdown-menu" role="menu"> <li><%= link_to 'Profile', edit_user_registration_path %></li> <li><%= link_to 'Log out', destroy_user_session_path, method: :delete %></li> </ul> </li> <% else %> <li><%= link_to 'Log In', new_user_session_path %></li> <li><%= link_to 'Sign Up', new_user_registration_path %></li> <% end %> </ul> </div> </div> </nav> 

user_signed_in? это вспомогательный метод Devise, который сообщает, вошел ли пользователь в систему или нет. current_user возвращает либо пользовательскую запись, либо nil , если никто не вошел в систему. Обратите внимание, что если вы вызывали свою модель по-разному во время генерации миграции Devise, эти вспомогательные методы также будут иметь разные имена! Для модели Admin это будет admin_signed_in? и current_admin . Метапрограммирование это круто.

Все маршруты (кроме root_path , конечно) также представлены Devise. Обратите внимание, что для destroy_user_session_path ( destroy_user_session_path ) по умолчанию требуется метод DELETE HTTP. Если вам это не нравится, измените config.sign_out_via внутри инициализатора devise.rb .

В целях стилизации я использую раскрывающееся меню Bootstrap. Если вы также используете его, понадобятся дополнительные действия. Dropdown опирается на код JavaScript и, используя Turbolinks , не будет корректно выполняться при переходе между страницами. Используйте jquery-turbolinks, чтобы исправить это:

Gemfile

 [...] gem 'jquery-turbolinks' [...] 

Не забудь бежать

 $ bundle install 

Теперь измените файл application.js :

application.js

 [...] //= require jquery //= require jquery.turbolinks //= require jquery_ujs //= require bootstrap/dropdown //= require turbolinks [...] 

Чтобы стилизовать специфичные для Devise флеш-сообщения, используйте метод Sass @extend в качестве простого исправления (не злоупотребляйте им, поскольку у этой директивы есть некоторые недостатки):

application.scss

 [...] .alert-alert { @extend .alert-warning; } .alert-notice { @extend .alert-info; } [...] 

Перезагрузите сервер и взгляните на выпадающее меню. Почему имя пользователя не отображается?

Strong_params и страница редактирования профиля

Если вы используете Rails с strong_params (которые включены в Rails 4 по умолчанию), потребуется еще один шаг:
атрибут :name должен быть в белом списке.

application_controller.rb

 [...] before_action :configure_permitted_parameters, if: :devise_controller? protected def configure_permitted_parameters devise_parameter_sanitizer.for(:sign_up) << :name devise_parameter_sanitizer.for(:account_update) << :name end [...] 

Мы добавили before_action ко всем контроллерам Devise, before_action в белый список атрибута :name для действий по регистрации и обновлению аккаунта (также :sign_in опция :sign_in ). Если у вас есть немного более сложный сценарий с вложенными хэшами или массивами, обратитесь к этому разделу документации.

Прежде чем перейти на страницу профиля, чтобы изменить свое имя, соответствующий вид должен быть обновлен:

просмотров / Завещание / регистрация / edit.html.erb

 <% header "Edit #{resource_name.to_s.humanize}" %> <%= form_for(resource, as: resource_name, url: registration_path(resource_name), html: { method: :put }) do |f| %> <%= devise_error_messages! %> <div class="form-group"> <%= f.label :name %> <%= f.text_field :name, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :email %> <%= f.email_field :email, class: 'form-control' %> <% if devise_mapping.confirmable? && resource.pending_reconfirmation? %> <span class="label label-info">Currently waiting confirmation for: <%= resource.unconfirmed_email %></span> <% end %> </div> <div class="form-group"> <%= f.label :password %> <%= f.password_field :password, autocomplete: "off", class: 'form-control' %> <span class="help-block">leave blank if you don't want to change it</span> </div> <div class="form-group"> <%= f.label :password_confirmation %><br /> <%= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control' %> </div> <div class="form-group"> <%= f.label :current_password %> <%= f.password_field :current_password, autocomplete: "off", class: 'form-control' %> <span class="help-block">we need your current password to confirm your changes</span> </div> <%= f.submit "Update", class: 'btn btn-primary' %> <% end %> <h3>Cancel my account</h3> <p>Unhappy? <%= button_to "Cancel my account", registration_path(resource_name), class: 'btn btn-danger', data: { confirm: "Are you sure?" }, method: :delete %> </p> <%= link_to "Back", :back, class: 'btn btn-default btn-sm' %> 

Обратите внимание, что пользователь также может изменить свой адрес электронной почты (который должен быть подтвержден, как мы уже обсуждали ранее), пароль и даже полностью удалить профиль.

Я не собираюсь показывать, как стилизованы представления других Devise — просмотрите мое GitHub репо, если вам интересно.

Отправка электронной почты и DelayedJob

Давайте кратко обсудим процесс отправки электронной почты. Прежде всего, вы должны помнить, что в средах разработки электронные письма не будут отправляться по умолчанию. Вы все равно сможете увидеть их содержимое в консоли. Чтобы включить отправку:

конфигурации / среда / development.rb

 [...] config.action_mailer.perform_deliveries = true [...] 

и настройте ActionMailer (см. примеры здесь ).

Далее для производства вам также нужно будет добавить аналогичную конфигурацию. Вот мой конфиг для демонстрационного приложения:

конфигурации / среда / production.rb

 [...] config.action_mailer.delivery_method = :smtp config.action_mailer.default_url_options = { host: 'sitepoint-devise.herokuapp.com' } ActionMailer::Base.smtp_settings = { :address => 'smtp.sendgrid.net', :port => '587', :authentication => :plain, :user_name => ENV['SENDGRID_USERNAME'], :password => ENV['SENDGRID_PASSWORD'], :domain => 'heroku.com', :enable_starttls_auto => true } [...] 

Поскольку это приложение работает на Heroku, я должен использовать одну из его надстроек для доставки почты (вы не сможете отправлять электронную почту напрямую). В моей настройке используется Sendgrid . Обратите внимание, что он работает по бесплатному тарифу, поэтому доставка почты может занять некоторое время.

Кстати, если вы хотите использовать собственный почтовик, измените настройку config.mailer внутри devise.rb .

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

Вставьте новый драгоценный камень:

Gemfile

 [...] gem 'delayed_job_active_record' [...] 

и беги

 $ bundle install $ rails generate delayed_job:active_record $ rake db:migrate 

установить гем и сгенерировать и применить требуемую миграцию (будет создана новая таблица для хранения запланированных задач).

Для Rails 4.2 измените файл application.rb, чтобы установить бэкенд очереди:

конфиг / application.rb

 [...] config.active_job.queue_adapter = :delayed_job [...] 

Теперь просто переопределите метод Devise в вашей модели:

модели / user.rb

 [...] def send_devise_notification(notification, *args) devise_mailer.send(notification, self, *args).deliver_later end [...] 

deliver_later означает, что отправка будет поставлена ​​в очередь. Большой!

Если вы собираетесь развернуть приложение в Heroku, создайте Procfile в корневом каталоге вашего проекта и добавьте следующую строку:

PROCFILE

 worker: rake jobs:work 

Обратите внимание, что вам придется включить хотя бы один рабочий процесс для обработки заданий, и это будет стоить вам около 35 долларов в месяц:

 $ heroku ps:scale worker=1 

Существует довольно подробное руководство по использованию DelayedJob в Heroku, поэтому обратитесь к нему для получения более подробной информации.

Обратите внимание, что я не включу фоновую отправку в моем демонстрационном приложении, но соответствующий код находится в репозитории GitHub.

Ограничение доступа

До сих пор мы проделали хорошую работу, но как насчет ограничения доступа к определенным страницам? Как это можно сделать?

Похоже, что Devise позаботится об этом тоже: вам нужно только использовать соответствующий метод в качестве before_action . Перво-наперво, нам нужна специальная страница для ограничения. Давайте назовем это «Секрет» для простоты:

конфиг / routes.rb

 [...] get '/secret', to: 'pages#secret', as: :secret [...] 

Мертвое простое представление:

просмотров / страниц / secret.html.erb

 <% header "Secret!" %> 

Вам даже не нужно добавлять secret метод к PagesController — Rails определит его неявно.

Немного измените меню:

просмотров / макеты / application.html.erb

 [...] <ul class="nav navbar-nav"> <li><%= link_to 'Home', root_path %></li> <% if user_signed_in? %> <li><%= link_to 'Secret', secret_path %></li> <% end %> </ul> [...] 

А теперь настройте контроллер:

pages_controller.rb

 [...] before_action :authenticate_user!, only: [:secret] [...] 

Эта before_action проверит, аутентифицирован ли пользователь перед вызовом secret метода. Неаутентифицированные пользователи будут перенаправлены на страницу входа с установленным флэш-сообщением «Пожалуйста, авторизуйтесь». Еще раз отметим, что для моделей с разными именами этот метод будет иметь другое имя ( authenticate_admin! Для модели Admin ).

Попробуйте это!

Использование расширений Devise

Большое сообщество разработчиков Devise разработало множество замечательных расширений, добавляющих еще больше функциональности. Давайте интегрируем Devise Zxcvbn с помощью Bit Zesty в качестве примера.

Это расширение используется для измерения надежности пароля и отклонения слабых паролей. Он опирается на zxcvbn-ruby, который, в свою очередь, является портом Ruby zxcvbn.js от Dropbox. Прочтите это официальное сообщение в блоге, чтобы узнать, как работает это решение.

Вставьте новый драгоценный камень:

Gemfile

 [...] gem 'devise_zxcvbn' [...] 

и беги

 $ bundle install 

Далее зарегистрируйте новый модуль для вашей модели:

модели / user.rb

 [...] devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable, :confirmable, :lockable, :zxcvbnable [...] 

Теперь User zxcvbnable (попробуйте произнести это). Существует только один параметр для этого расширения:

конфиг / Инициализаторы / devise.rb

 [...] config.min_password_score = 0 [...] 

Это в основном означает, насколько надежным должен быть пароль (чем выше, тем сильнее). Сила интерпретируется как расчетное время взлома:

  • 0 — расчетное время взлома составляет менее 10 ** 2 секунд.
  • 110 ** 4 секунды.
  • 210 ** 6 секунд.
  • 310 ** 9 секунд.
  • 4 — бесконечность (ну, не совсем, но мы можем считать пару веков бесконечностью, в данном случае).

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

Наконец, настройте сообщение об ошибке:

конфиг / локали / devise.en.yml

 [...] en: errors: messages: weak_password: "is not strong enough. Consider adding a number, symbols or more letters to make it stronger." [...] 

Попробуйте разные пароли и проверьте, насколько они надежны.

Измерение надежности паролей на стороне клиента

В заключение позвольте мне показать вам, как добавить zxcvbn на стороне клиента. Скачайте и подключите этот файл в вашем проекте. Создайте новый файл CoffeeScript со следующим содержимым:

global.coffee

 jQuery -> displayHint = (strength, crack_time) -> msg = 'Password is ' + strength + ' (time to break it: ' + crack_time + ')' estimate_message = this.next('.estimate-message') if estimate_message.length > 0 estimate_message.text msg else this.after '<span class="help-block estimate-message">' + msg + '</span>' $('form').on 'keyup', '.estimate-password', -> $this = $(this) estimation = zxcvbn($this.val()) crack_time = estimation.crack_time_display switch estimation.score when 0 then displayHint.call($this, "very weak", crack_time) when 1 then displayHint.call($this, "weak", crack_time) when 2 then displayHint.call($this, "okay", crack_time) when 3 then displayHint.call($this, "strong", crack_time) when 4 then displayHint.call($this, "very strong", crack_time) return 

и подключить его:

application.js

 [...] //= require global [...] 

score возвращает числа от 0 до 4 — мы говорили о них только что — так что это кажется наиболее удобным способом измерения силы. crack_time_display возвращает приблизительное время, необходимое для взлома пароля, в удобном формате («3 дня», «4 года», «века» и т. д.).

Теперь назначьте класс с estimate-password для любого поля пароля, например:

просмотров / Завещание / регистрация / new.html.erb

 [...] <div class="form-group"> <%= f.label :password %> <%= f.password_field :password, autocomplete: "off", class: 'form-control estimate-password' %> <% if @validatable %> <span class="help-block"><%= @minimum_password_length %> characters minimum</span> <% end %> </div> <div class="form-group"> <%= f.label :password_confirmation %> <%= f.password_field :password_confirmation, autocomplete: "off", class: 'form-control estimate-password' %> </div> [...] 

Конечно, это самое простое решение, поэтому не стесняйтесь расширять его.

Вывод

Это подводит нас к концу этой статьи. Мы интегрировали Devise в приложение, посмотрели его модули и настройки и добавили расширение. Доступно гораздо больше функций и расширений, поэтому я рекомендую вам взглянуть на официальную вики , в частности на практические рекомендации — в ней более 90 небольших, но полезных руководств.

Надеюсь, вам понравилась вторая часть серии «Аутентификация с помощью Rails»! В следующей статье мы собираемся обсудить аутентификацию с OAuth 2.

Удачного кодирования и до скорой встречи!